Closures in Ruby
Ruby supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.
# This method int_seq returns a Proc object, which
# we define anonymously in the body of int_seq. The
# returned Proc closes over the variable i to
# form a closure.
def int_seq
i = 0
-> { i += 1 }
end
# We call int_seq, assigning the result (a Proc)
# to next_int. This Proc captures its
# own i value, which will be updated each time
# we call next_int.
next_int = int_seq
# See the effect of the closure by calling next_int
# a few times.
puts next_int.call
puts next_int.call
puts next_int.call
# To confirm that the state is unique to that
# particular Proc, create and test a new one.
new_ints = int_seq
puts new_ints.call
To run the program, save it as closures.rb
and use the ruby
command:
$ ruby closures.rb
1
2
3
1
In Ruby, closures are typically implemented using Proc objects or lambda functions. The ->
syntax used in this example is a shorthand for creating a lambda.
The int_seq
method returns a new Proc each time it’s called. This Proc maintains its own state (the value of i
), which persists between calls to the Proc.
When we call next_int
multiple times, we see the value incrementing, demonstrating that the Proc is maintaining its state. When we create a new Proc with new_ints = int_seq
, it starts with its own fresh state, separate from next_int
.
This example showcases how closures in Ruby can be used to create function factories, each producing a function with its own encapsulated state.