&Blocks, &Procs, &Lambdas
Closures are technique for implementing lexical scoping. They encapsulate functions, variables, and an environment. Blocks, Procs, and Lambdas are all examples of closures in Ruby.
Blocks are chunks of code that respond to a
yield statement. You’ve definitely used Blocks before. Probably used one this morning. Most enumerator methods, like
reduce, accept a block as an argument.
1 2 3 4 5 6 7 8
All the code between the
end sandwich is a Block. Behind the scenes the
each enumerator method is using a
yield statement to pass the string into the Block we provided. If you’ve ever seen the error:
no block given (yield) (LocalJumpError) you’ve encountered a method that expected a block but did not receive it. A monkey-patched example reveals the internals of how methods that expect a Block work:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Everybody uses Blocks. They are fundamental building_blocks_ of Ruby programing.
Procs (short for “procedures”) are like Blocks with names. Formally, Procs are “anonymous functions” that can be represented as an object. Procs can be saved with a variable and reused throughout the program. Unlike Blocks, Procs are actual objects constructed through use of the
1 2 3
However, Procs respond to
.call instead of
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Procs help your programs stay DRY. If you catch yourself using the same Block logic repeatedly within your application then store that logic in Proc to avoid repetition.
Lambdas are basically strict Procs with different
return behavior. Both Lambdas and Procs are instances of the
Proc class and both act like “anonymous functions”, however, Lambdas respect “arity” (a fancy way of saying that they will break if given an incorrect number of arguments, just like methods).
1 2 3 4 5
Alternatively, Lambdas can be created in what may be the most bad-ass name for obscure syntax — “stabby lambda”:
1 2 3
Lambdas and Procs also handle
return statements differently. Procs interpret the
return within the scope that called the proc. Lambdas, on the other hand, interpret the
return within the scope of the lambda (exactly the same way a method would handle a
return). This is might seem like an esoteric difference but can easily cause some problems.
Ultimately, choosing between Lambdas and Procs really depends on preference. Both are perfect for encapsulating and storing code.