Blocks are closures that can be passed to any method in ruby. A block gets special handling and does not need to be explicitly defined in a methods parameter list.
1 2 3 4 5 6 7 8 9 def dont_tell() yield "i sleep with a blanky." if block_given? end dont_tell do |dirty_secret| puts dirty_secret end dont_tell
In the above example, the method dont_tell is defined and yields execution back to an implicit block argument via the yield keyword. Line 5 invokes the dont_tell method passing along a block parameter that accepts a secret as a single parameter and writes it to stdout.
Line 9 also invokes the dont_tell method but without an explicit block parameter. The call to Kernel#block_given? prevents an attempt to invoke a block if one is not given.
Block’s can be converted to Proc’s using an & and back to a block using &.
1 2 3 4 5 6 7 8 9 10 11 12 13 def will_it_blend?(&block) [1,3,5,7,9,10].each(&block) end will_it_blend? do |number| if number.even? raise "Boom" else print "." sleep 1 end end
On line 1 the block is converted to a block, then on line 2 the proc is converted back to a block and passed to each.
A proc is an object that represents a block of code. A Proc can be created in a couple of ways.
You can invoke a proc by calling it’s call method.
A lambda is a special kind of proc. To create one you can invoke Kernel#lambda.
There are two main differences between a proc and a lambda.
when invoking a lambda the number of parameters passed in must match the number of parameters defined in the definition.
procs don’t care.
When returning from a lambda, it exits the scope of the lambda back to the caller. Very much like a method invocation.
When this example is run returning from the lambda only returns from the lambda. Execution returns to the calling method.
If we run the same example again, only swap a lambda for a proc. Then we see the following output.
When we return from a proc, it exits the method that called the proc.