从底层来看,使用【块】需要分两步,第一步,将代码打包备用;第二步,调用【块】(通过yield语句)来执行代码。这种“先打包代码,以后调用”的机制并不是【块】的专利。在ruby中,至少还有以下三种方法可以用来打包的代码。

1、  使用proc,proc基本上就是一个由块转换成的对象;

2、  使用lambda,它是proc的近亲;

3、  使用方法。

本文将重点讨论proc与lambda的区别。

proc与lambda之间有两个主要区别,第一个区别与return关键字有关,第二个区别与参数校验有关。

区别之一:return

在lambda中,returen是指从lambda对象返回;

def add(lam)
   lam.call + 10
end
lam = lambda { return 100 }
puts add(lam)  #=>110

在proc中,returen不是从proc返回,而是从定义proc的作用域返回。

def another_add()
  my_proc = Proc.new{return 10}
  result = my_proc.call #=>这里就从another_add返回了
  puts "this is unreachable code" #=>这行代码不会被执行
end
puts another_add  #=>10

区别之二:检查参数的方式

如果调用lambda的参数数量不对,则它会失败,同时抛出一个ArgumentError错误;而proc则会把传递进来的参数调整为自己期望的参数形式:

p = Proc.new { |a,b| [a,b]}
p.call(1,2,3)   #=> [1,2]
p.call(1)      #=> [1, nil]

如果参数比期望的多,那么proc会忽略多余的参数;如果参数数量不足,那么对未指定的参数,proc会赋予一个nil值。

总之,lambda更加直观,因为它更像一个方法,它不仅对参数数量检查更加严格,而且在调用return时只从代码中返回。由于这些原因,很多ruby使用者把lambda作为第一选择,除非他们需要使用proc的特殊功能。

注:关于Kernel#proc

在ruby1.8中,Kernel#proc()实际上只是Kernel#lambda()的别名,由于程序员的不断抗议,在ruby1.9中,proc()变成了Proc.new()的别名。