๐ŸŽ“ A1Learner
๐Ÿ”
0 of 34 lessons completed

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.call

Two 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.call

A 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 total

Example

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.call

Key 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?