Ruby Closures
A stored block that remembers the variables around it is a closure. The proc keeps using those variables after the method that made it has finished.
A counter that remembers
make_counter builds a proc around a count that starts at 0. Each call adds 1 and prints the new count.
def make_counter
count = 0
Proc.new do
count = count + 1
puts count
end
end
counter = make_counter
counter.call
counter.call
counter.callTwo counters, two counts
Two calls to make_counter build two separate counts. Each counter raises only its own count.
def make_counter
count = 0
Proc.new do
count = count + 1
puts count
end
end
first = make_counter
second = make_counter
first.call
first.call
second.callA proc changes its captured variable
The proc adds 5 to total each time it runs. total sits outside the proc, and the change stays between calls.
total = 0
add_five = Proc.new do
total = total + 5
end
add_five.call
add_five.call
puts totalExample
def make_greeter(name)
Proc.new do
puts "Hello, #{name}"
end
end
ana = make_greeter("Ana")
ben = make_greeter("Ben")
ana.call
ben.call
ana.callKey points
- A proc remembers the local variables where it was built.
- That memory is called a closure.
- Each call to the building method makes a fresh set of variables.
- Two procs built by two calls hold separate memories.
- A proc can change the variable it captured.
In this example, make_greeter builds one proc per name, and each proc remembers its own name. The Ana proc prints its greeting, then the Ben proc prints its own. The Ana proc still remembers Ana on its second call, which is the closure at work.
Note
The captured variable lives as long as the proc lives.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does a closure remember?