Closures in Crystal

Crystal 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 function `int_seq` returns another function, which
# we define anonymously in the body of `int_seq`. The
# returned function 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 function)
# to `next_int`. This function value 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 function, create and test a new one.
new_ints = int_seq()
puts new_ints.call

To run the program, save it as closures.cr and use the Crystal compiler:

$ crystal closures.cr
1
2
3
1

In Crystal, closures are implemented using anonymous functions (also known as lambdas or Procs). The syntax -> is used to define an anonymous function. The call method is used to invoke the function.

The int_seq function returns a closure that increments and returns a counter. Each time the closure is called, it increments its own i variable and returns the new value.

The last feature of functions we’ll look at for now is recursion.