Jim Weirich:
This is how I explain it… Ruby has Procs and Lambdas. Procs are created with
Proc.new { }
, lambdas are created withlambda {}
and->() {}
.
In Ruby 1.8,
proc {}
creates lambda, and Ruby 1.9 it creates procs (don't ask).
Lambdas use method semantics when handling parameters, procs use assignment semantics when handling parameters.
This means lambdas, like methods, will raise an ArgumentError when called with fewer arguments than they were defined with. Procs will simply assign nil to variables for arguments that were not passed in.
Starting from Ruby 1.9, both procs and lambdas—like methods—support defining arguments with default values. To lambdas, such arguments are then optional at call time.
Lambdas act like anonymous functions w.r.t. the return statement (i.e.
return
will return from the lambda). Procs are invisible toreturn
, so a return statement will return from the enclosing function. The technical way to say this is that Procs follow the Tennent Correspondence Principle w.r.t. return statements. This allows you to wrap some code in a proc and immediately call the proc without changing the semantics of the code.
That leaves blocks. Blocks don't actually exist as things manipulated by the Ruby language. When I talk about blocks, I am referring to the syntactical construct of putting
do/end
or{}
after a method invocation. When you write code with this syntactical construction, Ruby arranges for the code in the block to be passed to method being called. MRI will create a proc object representing the block only if you reference the block with a&block
parameter in the calling sequence. This is a mere implementation detail.
A: “Everything is an object in Ruby! :D”
B: “What is the class of a block?”
A: “:-[”
Very concise. Thank you for sharing!