[Ruby] Blocks -- Ex

Iterating with Blocks

Let's build a Library class that will manage our growing collection of games. We've already written a listmethod that prints the names of all our games, but it uses an ugly for loop to iterate the list. Refactor it to use each with a block instead.

复制代码
#seed.rb

GAMES = [
  Game.new('Contra', year: 1987, system: 'NES'),
  Game.new('Civilization', year: 1991, system: 'PC'),
  Game.new('The Legend of Zelda', year: 1986, system: 'NES'),
  Game.new('Mega Man X2', year: 1995, system: 'SNES'),
  Game.new('Super Metroid', year: 1994, system: 'SNES'),
  Game.new('Sim City 2000', year: 1993, system: 'PC'),
  Game.new('Starcraft', year: 1998, system: 'PC')
]
复制代码
复制代码
#game.rb

class Game
  attr_accessor :name, :year, :system
  attr_reader :created_at
 
  def initialize(name, options={})
    self.name = name
    self.year = options[:year]
    self.system = options[:system]
    @created_at = Time.now
  end
end
复制代码
复制代码
class Library
  attr_accessor :games

  def initialize(games = [])
    self.games = games
  end

  def list
    for i in 0...(games.length)
      game = games[i]
      puts game.name
    end
  end
end
复制代码

Answer:

复制代码
class Library
  attr_accessor :games

  def initialize(games = [])
    self.games = games
  end

  def list
    games.each do |game|
      puts game.name
    end    
  end
end
复制代码

 

Yielding to Blocks

We'd like to be able to operate on our games by system. Implement an each_on_system method that iterates over our games using each and yields to a block for every game on the requested system. To test that it's working, we'll call each_on_system with a simple block that prints a message for every Super Nintendo game in our library. See the example.rb below.

library = Library.new(GAMES)
library.each_on_system("SNES") { puts "Found a Super Nintendo game" }

Answer:

复制代码
class Library
  attr_accessor :games

  def initialize(games = [])
    self.games = games
  end

  def each_on_system(system)
    self.games.each do |game|
      yield if game.system == system
    end
  end
end
复制代码

 

Passing Arguments to Blocks

Our each_on_system method is working, but it's not very useful unless the block has access to each game that we find. Modify each_on_system to pass the Game object into the block so we can print its name.

复制代码
class Library
  attr_accessor :games

  def initialize(games = [])
    self.games = games
  end

  def each_on_system(system)
    games.each { |game| yield game if game.system == system}  
  end
end
复制代码

 

Returning Values from Blocks

Earlier we wrote a list method that prints the name of each game in our library. We can make the output formatting more flexible by allowing a block to be passed to the list method. We'll yield each game to the block and allow the block to format and return a string for us to display. Modify the list method to yield to a block and print whatever the block returns.

library = Library.new(GAMES)
library.list { |game| "#{game.name} (#{game.system}) - #{game.year}" }

Answer:

复制代码
class Library
  attr_accessor :games

  def initialize(games = [])
    self.games = games
  end

  def list
    games.each do |game|
      puts yield game
    end
  end
end
复制代码

 

Using Enumerable

Let's add the power of Ruby's Enumerable module to our game library. Implement an each method that yields each game in the library. Finally, include the Enumerable module so that we'll be able to call methods like select and collect on our library.

library = Library.new(GAMES)
library.select { |game| game.year == 1986 }
library.collect { |game| game.system }

Answer:

复制代码
class Library
  include Enumerable
  attr_accessor :games

  def initialize(games = [])
    self.games = games
  end

  def each
    self.games.each {|game| yield game}
  end
end
复制代码

 

Refactoring with Blocks

Now that our library is complete, let's play some games! A friend has given us his Emulator class to use, and we've implemented methods to play a game and grab a screenshot. But look at all that duplicated code in play and screenshot. Refactor the duplication (the beginnew and rescue parts) into a private method called emulate that handles the emulator setup and exception handling and yields the emulator instance to a block.

复制代码
class Emulator
  def initialize(system)
    # Creates an emulator for the given system
  end
 
  def play(game)
    # Runs the given game in the emulator
  end
 
  def start(game)
    # Loads the given game but doesn't run it
  end
 
  def screenshot
    # Returns a screenshot of the currently loaded game
  end
end
复制代码
复制代码
class Game
  attr_accessor :name, :year, :system
  attr_reader :created_at

  def initialize(name, options={})
    self.name = name
    self.year = options[:year]
    self.system = options[:system]
    @created_at = Time.now
  end

  def play
    begin
      emulator = Emulator.new(system)
      emulator.play(self)
    rescue Exception => e
      puts "Emulator failed: #{e}"
    end
  end

  def screenshot
    begin
      emulator = Emulator.new(system)
      emulator.start(self)
      emulator.screenshot
    rescue Exception => e
      puts "Emulator failed: #{e}"
    end
  end
end
复制代码

Answer:

复制代码
class Game
  attr_accessor :name, :year, :system
  attr_reader :created_at

  def initialize(name, options={})
    self.name = name
    self.year = options[:year]
    self.system = options[:system]
    @created_at = Time.now
  end

  def play
    emulate do |emulator|
      emulator.play(self)
    end
  end

  def screenshot
    emulate do |emulator|
      emulator.start(self)
      emulator.screenshot
    end
  end
  
  private 
  
  def emulate
        emulator = Emulator.new(system)
        yield emulator
    rescue Exception => e
      puts "Emulator failed: #{e}"     
  end
  
end
复制代码

 

posted @   Zhentiw  阅读(412)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示