Block、Procs与Lambda #
Block #
定义 Block #
Block 代表一个可执行的代码块
{ |x| puts "x * 3 is #{x * 3}" }
在函数中可以通过 yield
调用传入的 Block 对象
def cube
puts 'You are in the method'
yield(3)
puts 'You are again back to the method'
yield(4)
end
cube { |x| puts "x * 3 is #{x * 3}" }
如果调用时没有传入 Block 的话,调用 yield
会发生错误,此时需要调用 block_given?
来判断是否存在。
def foo
yield if block_given?
end
foo { puts 'foobar' }
foo
隐式 Block(匿名) 到显式 Block(带名) #
def cube2(x, &f)
f.call(x)
end
cube2(4){ |x| puts "x * 4 is #{x * 4}" }
显式 Block 到隐式 Block #
def calculation(a, b)
yield(a, b)
end
add = lambda{|x, y| x + y}
puts calculation(3, 4, &add)
Syntax #
Ruby 支持两种 Block 的语法
第一种
addition = lambda {|a, b| a + b }
第二种
addition = lambda do |a, b|
a + b
end
Procs #
创建 Proc #
Proc 代表一个可以被执行的代码块,Proc 可以拥有参数。
定义一个 Proc
cube = Proc.new { |x| x * 3 }
应用 Proc #
符号 &
可以用于引用一个 Proc 类型的变量
print [1, 2, 3].collect!(&cube)
&
也可以用与引用代表函数的 Symbol 对象
puts [1, 2, 3].collect(&:to_s)
Proc 实例也可以直接调用 call()
方法进行调用
print cube.call([2, 4, 6])
判断函数是否存在 #
puts [1, 2, 3].respond_to?(:collect)
Lambda #
创建 Lambda #
Lambda 实际就是 Proc 的语法糖
定义一个 Lambda
triple = lambda { |x| x * 3 }
应用 Lambda #
符号 &
可以用于引用一个 Lambda 类型的变量
print [1, 2, 3].collect!(&triple)
Lambda 实例也可以直接调用 call()
方法进行调用
print triple.call([2, 4, 6])
Lambda vs Proc #
Lambda 虽然是 Proc 的语法糖,但是实际还是有一些区别。 Lambda 会检查参数的个数,而 Proc 不会。也就是说 Proc 如果参数数量不对,缺少的参数会当做 nil,多出来的会被忽略。 并且Lambda 执行完后不会立即返回调用处,而 Proc 会。
区别的例子
def batman_ironman_proc
victor = Proc.new { return "Batman will win!" }
victor.call
"Iron Man will win!"
end
puts batman_ironman_proc # Batman will win!
def batman_ironman_lambda
victor = lambda { return "Batman will win!" }
victor.call
"Iron Man will win!"
end
puts batman_ironman_lambda # Iron Man will win!