Closures
In Ruby, procs and lambdas are
closures. The term “closure” comes from the early
days of computer science; it refers to an object that is both an
invocable function and a variable binding for that function. When you
create a proc or a lambda, the resulting Proc
object holds not just the executable
block but also bindings for all the variables used by the block.
You already know that blocks can use local variables and method
arguments that are defined outside the block. In the following code, for
example, the block associated with the collect
iterator uses the method argument
n
:
# multiply each element of the data array by n def multiply(data, n) data.collect {|x| x*n } end puts multiply([1,2,3], 2) # Prints 2,4,6
What is more interesting, and possibly even surprising, is that if
the block were turned into a proc or lambda, it could access n
even after the method to which it is an
argument had returned. The following code demonstrates:
# Return a lambda that retains or "closes over" the argument n def multiplier(n) lambda {|data| data.collect{|x| x*n } } end doubler = multiplier(2) # Get a lambda that knows how to double puts doubler.call([1,2,3]) # Prints 2,4,6
The multiplier
method returns a
lambda. Because this lambda is used outside of the scope in which it is
defined, we call it a closure; it encapsulates or “closes over” (or just
retains) the binding for the method argument n
.
Closures and Shared Variables
It is important to understand that a closure does not just retain ...
Get The Ruby Programming Language now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.