Block、Procs与Lambda

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!
沪ICP备17055033号-2