As long as the block variable is in
scope, it will hold its own reference to data, and that instance of data will not be
destroyed (even though the get_closure function returns). Note that each time
get_closure is called, data references a different variable (since it is function-local):
block = get_closure
block2 = get_closure
block.call.object_id # => 76200
block2.call.object_id # => 76170
Metaprogramming Techniques | 23
A classic example of closures is the make_counter function, which returns a counter
function (a Proc) that, when executed, increments and returns its counter. In Ruby,
make_counter can be implemented like this:
def make_counter(i=0)
lambda { i += 1 }
end
x = make_counter
x.call # => 1
x.call # => 2
y = make_counter
y.call # => 1
y.call # => 2
The lambda function creates a closure that closes over the current value of the local
variable i. Not only can the variable be accessed, but its value can be modified. Each
closure gets a separate instance of the variable (because it is a variable local to a particular
instantiation of make_counter). Since x and y contain references to different
instances of the local variable i, they have different state.
Metaprogramming Techniques
Now that we??™ve covered the fundamentals of Ruby, we can examine some of the
common metaprogramming techniques that are used in Rails.
Although we write examples in Ruby, most of these techniques are applicable to any
dynamic programming language.
Pages:
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50