-
Notifications
You must be signed in to change notification settings - Fork 1
BlocksProcsLambdas
WIP
These comments were made on the Ruby Rogues mailing list.
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.
Lambdas act like anonymous functions w.r.t. return (i.e. "return" will return from the lambda). Procs are invisible to return, 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. I believe JRuby creates a Proc object everytime is block is passed to a method, whether the method references the block or not.
Jim Weirich
Lambdas use method semantics when handling parameters, procs use assignment semantics when handling parameters.
That means lambdas will explode when called with the wrong number of arguments same way methods do.Procs will simply assign nil to variables for arguments that weren't explicitly passed in.Both lambdas and procs support default values in their arguments definition the same way methods support them.
Mislav Marohnic
Assignment semantics means that in "proc { |a, b| ...}.call(1, 2, 3)", the parameters a and b get their values in the same way that in "a, b = 1, 2, 3" the variables a and b get their values.
Method call semantics means that in "lambda { |a, b| ...}.call(1, 2)", the parameters a and b get their values in the same way that in "def foo(a, b); end; foo(1, 2)" the method parameters a and b get their values.
Jim Weirich
I've always found this blog entry by Neal Gafter (w.r.t. clojures in Java) to be a help in understanding why procs return behavior is a good thing. http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html
Jim Weirich
Concepts
Elements
Guidelines
Miscellaneous
Techniques