Ruby中的proc和lambda有什么区别?

你什么时候使用一个而不是另一个?

一个区别在于他们处理论点的方式。 使用proc {}Proc.new {}创buildproc是等同的。 但是,使用lambda {}会为您提供一个检查传递给它的参数数量的过程。 来自ri Kernel#lambda

相当于Proc.new ,除了生成的Proc对象检查调用时传递的参数的数量。

一个例子:

 p = Proc.new {|a, b| puts a**2+b**2 } # => #<Proc:0x3c7d28@(irb):1> p.call 1, 2 # => 5 p.call 1 # => NoMethodError: undefined method `**' for nil:NilClass p.call 1, 2, 3 # => 5 l = lambda {|a, b| puts a**2+b**2 } # => #<Proc:0x15016c@(irb):5 (lambda)> l.call 1, 2 # => 5 l.call 1 # => ArgumentError: wrong number of arguments (1 for 2) l.call 1, 2, 3 # => ArgumentError: wrong number of arguments (3 for 2) 

另外,正如Ken指出的那样,在lambda中使用return函数将返回该lambdaexpression式的值,但是在proc中使用return函数返回的是封闭块。

 lambda { return :foo }.call # => :foo return # => LocalJumpError: unexpected return Proc.new { return :foo }.call # => LocalJumpError: unexpected return 

所以对于大多数快速的使用来说,它们是相同的,但是如果你想要自动严格的参数检查(有时也可以帮助debugging),或者如果你需要使用return语句来返回proc的值,可以使用lambda

proc和lambdas之间的真正区别与控制stream关键字有关。 我正在谈论returnraisebreakredoretry等 – 这些控制字。 假设你在一个proc中有一个return语句。 当你调用你的proc的时候,它不但会把你抛出,而且还会从封闭的方法返回,比如:

 def my_method puts "before proc" my_proc = Proc.new do puts "inside proc" return end my_proc.call puts "after proc" end my_method shoaib@shoaib-ubuntu-vm:~/tmp$ ruby a.rb before proc inside proc 

最后的方法,从来没有执行过,因为当我们叫我们的过程,它的return倾销我们的方法。 但是,如果我们将proc转换为lambda,我们可以得到以下结果:

 def my_method puts "before proc" my_proc = lambda do puts "inside proc" return end my_proc.call puts "after proc" end my_method shoaib@shoaib-ubuntu-vm:~/tmp$ ruby a.rb before proc inside proc after proc 

lambda中的返回只会将我们从lambda本身中抛出,并且封闭的方法继续执行。 控制stream关键字在proc和lambdas中处理的方式是它们之间的主要区别

除了jtbandes的回答之外, return语句在proclambda返回的内容也有所不同。

这有点微妙。 它们都是创build闭包的方法,并且都返回Proc对象。 实际上还有第三种方式 – Proc.new 。 不同之处在于它们的行为方式,具体取决于您使用的是Ruby 1.8还是1.9(事实上,在Ruby 1.9中有另一种方法来创build它们)。 在一般情况下,差异不是你需要担心的。 只有当你关心严谨时,才会有所作为。 何时使用lambda,何时使用Proc.new? 涵盖差异相当不错。

一般来说,lambda比proc更直观,因为它们更类似于方法。 他们对团队非常严格,当你致电退货时他们只是退出。 出于这个原因,许多Ruby专家使用lambda作为第一select,除非他们需要proc的特定function。

Procs:Proc对象。 像块一样,它们在它们被定义的范围内进行评估。 Lambdas:也是类Proc对象,但是和常规的Proc略有不同。 他们像块和过程一样closures,因此他们在他们定义的范围内被评估。

创build过程

 a = Proc.new { |x| x 2 } 

创buildlambda

b = lambda { |x| x 2 b = lambda { |x| x 2 }

proc和lambda之间的区别在于,proc只是代码的一个副本,依次replace参数,而lambda是一个类似于其他语言的函数。 (返回行为,参数检查)