开发者

Need a memorable explanation of a proc and lambda

I've tried reading about procs and lambda's but I have to keep re-reading the definition.

Can someone explain it to me开发者_如何学C in a way that is clear and memorable?


Edited: After reading other good answers here, I offer the following distillation that might save you some re-reading:

(l)ambda -  
(L)ocal return  
(L)ooks at the arguments  

(p)roc -  
(P)ops you out of the method when it returns.  
(P)ermits different arguments  

Einstein said to "... make things as simple as possible, but no simpler." If he had stack overflow, he would have pointed you here:

What are the differences between a proc and lambda?

or here:

What's the difference between a proc and a lambda in Ruby?

hth -

Perry


A few resources:

  • When to use lambda, when to use Proc.new?
  • Understanding Ruby Blocks, Procs and Lambdas

There's also an entire chapter in the Read Ruby 1.9 book


The way I think about them is that a lambda behaves more like a function and a Proc or block behaves more like a control structure.

I think the best way to understand why the two exist and what the difference is is to understand how each is used. Take this code for example:

def find (elem)
  @array.each { |item| return item if item == elem }
  return false
end

It's obvious to anyone familiar with Ruby what happens here, but ask yourself what you are returning from when that return is called. What you expect, and what happens, is that the method itself returns. Even though we are inside a block of code, it is the method returning, not just the block. That is how a Proc behaves, and it's what lets us use an .each loop and return from it just like we would in an equivalent for loop.

On the other hand, lambdas are like functions. If you return from inside a lambda, it exits only from the lambda.

def find (elem)
  l = lambda { |item| return item if item == elem }
  @array.each(&l)
  return false
end

Here, the method would always return false due to the final line not being bypassed by a return call in the lambda. Lambdas are functions and return from themselves, whereas Procs return from the enclosing method.

So, Procs and blocks and return from the method using them (like a loop would), while lambdas (like methods) return from themselves.


Procs behave like blocks. Lambdas behave like methods.

I.e. return inside a Proc behaves like return inside a block and argument binding for Procs works the same as argument binding for blocks. return inside a lambda works like return inside a method and argument binding for lambdas works the same as argument binding for methods.

Note, however, that lambdas are Procs, i.e. they are instances of the Proc class. The difference between them is whether Proc#lambda? is true or false.

Note also that in older versions of Ruby, Kernel#proc created a lambda and not a Proc, which was utterly confusing. This has been fixed in modern versions of Ruby, where Kernel#proc is now equivalent to Proc.new and thus creates a Proc.

Kernel#lambda and the lambda literal syntax (->(x, y) { x + y }) always create a lambda, Proc.new always creates a Proc and Kernel#proc depends on the Ruby version.


In a Proc:

  • A return statement returns out of the calling context -- for instance all the way out of the method or context that calls the Proc, rather than just out of the Proc block.
  • It does not throw an exception for a incorrect number of arguments passed

In a lambda:

  • A return statement returns control to the calling context -- out of the block but not out of the method.
  • It throws an exception if the incorrect number of arguments are given, just like a method would.


Like Jorg W Mittag says, Procs behave like blocks, and lambdas behave like methods.

The way I memorize it is "proc" rhymes with "block".

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜