Closures in Ruby

The complete title for this post is: Closures in Ruby make my head hurt. I’ve had a rough idea of how closures work (from my JavaScript experience), but I just watched An Introduction Blocks, Lambdas and Closures in Ruby and I’ve realized that I my knowledge is a mere drop in the ocean.

I would highly recommend this video to anyone who is looking for a better understanding of these three topics.

To get started, let’s look at a very basic example of a closure.

def run_proc(p)
  p.call
end

name = "Bob"
puts_name = proc { puts name }
run_proc puts_name
# Bob

This code obviously works, but keep in mind what is really going on here – we are creating a proc which references the name variable. We then execute the block in the context of the run_proc method, where the name variable doesn’t exist! So this little snippet of code is actually doing something really complex.

Ruby actually attaches the name variable to the block which then makes it available when we want to use it! This is called a closure.

Let’s look at another example, using a lambda instead of a proc.

def run_lambda(l, val)
  l[val]
end

a = 5
multiply_by_a = lambda do |x| 
  x * a
end

puts run_lambda(multiply_by_a, 2)
# 10

Again, this works as we expected it to – the a variable is attached to the lambda and can be accessed when the lambda is executed. Now we can try something really strange.

def run_lambda(l, val)
  l[val]
end

a = 5
multiply_by_a = lambda do |x| 
  x * a
end

a = 10
puts run_lambda(multiply_by_a, 3)
# 30

What this snippet is illustrating is that Ruby closures actually attach a reference to the variable being used. That’s why we can update the a variable and have the lambda use the updated value – this is actually different to how a number of other languages implement closures. Happy coding.