之前看过codeschool的rubybits的教程,但是看的比较快,掌握的不是太扎实,重新复习下rubybits2的课程,记录一些笔记。
Proc
创建Proc
可以使用 Proc.new 创建一个Proc类的实例,Proc.new返回一个Proc类的对象。比如在codeschool rubybit2 channenge1的main.rb文件里使用Proc.new创建的print_details,这个proc接受一个game实例的参数并打印信息。
library = Library.new(GAMES)
print_details = Proc.new do |game|
puts "#{game.name} (#{game.system}) - #{game.year}"
end
library.exec_game("Contra", print_details)
library.exec_game("Contra", print_details) 这句代码中proc可以直接作为参数传递。
调用proc
在library.rb的exec_game方法中接受传递的参数并作用于game实例,其中exec_game方法中action是显示传递的proc,每个proc都有一个call方法,调用call方法就会执行这个proc。
代码:
class Library
attr_accessor :games
def initialize(games)
@games = games
end
def exec_game(name, action)
game = games.detect { |game| game.name = name }
action.call(game) if game.name == "Contra"
end
end
使用lambda 重构
上面例子中的Proc.new可以用lambda代替
print_details = lambda {|game| puts "#{game.name} (#{game.system}) - #{game.year}" }
Ruby 新的lanbda语法
ruby1.9后支持的新的语法
print_details = ->(game){ puts "#{game.name} (#{game.system}) - #{game.year}" }
改变
- lambda关键字改为 ->
- 参数在->后面并在括号里,在大括号之外
proc 到 block
使用&proc
的形式将proc作为blcok传递
例如
library = Library.new(GAMES)
library.each { |game| puts "#{game.name} (#{game.system}) - #{game.year}" }
可以这样
library = Library.new(GAMES)
print_detail = Proc.new do |game|
puts "#{game.name} (#{game.system}) - #{game.year}"
end
library.each(&print_detail)
symbol的to_proc
经常看到这样的写法
def names
games.map(&:name)
end
ruby允许用&开头的符号作为代码块被传递到一个迭代器中,这段代码中将符号(symbol) :name转换成proc传递给map,等价于
def names
games.map { |game| game.name }
end
optional blocks
ruby中block可以是可选的参数,ruby提供了block_given? 方法让我们判断是否有block传递,比如这段代码中的list方法,
list有block传递的时候,调用block,没有的调用game.name
class Library
attr_accessor :games
def initialize(games)
@games = games
end
def list
games.each do |game|
if block_given?
puts yield game
else
puts game.name
end
end
end
proc和lambda的区别
- lambda会进行参数检查,proc不会
- proc执行return语句,它会从代码块所在的方法中返回,而lambda仅仅从lambda自身返回,会继续执行方法后面的语句
others:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。