Why Ruby Procs are Closures

Procs are a Ruby object representation of an anonymous function and are an example of a closure because they can be passed around and still retain the bindings that were in place when the Proc was defined. A program’s bindings to self and local variables at a given point in time are referred to as the lexical scope or lexical environment. The following code creates a proc, calls it, and shows the bindings in place when the proc is called.

class Doug
  p self # => Doug
  x = 'tv show'
  best_friend = 'skeeter'
  p local_variables # => [:x, :best_friend]
  @pr = Proc.new { "self: #{self}, local_variables: #{local_variables}" }
  @pr.call # => "self: Doug, local_variables: [:x, :best_friend]"
end

The @pr proc has access to the bindings (self and local variables) that were in scope when the proc was defined. Ruby procs are closures, so if the program’s scope changes, the proc will still have access to the bindings that were in place when it was originally defined.

pr = Proc.new do
  x = 25
  y = 33
  "self: #{self}, local_variables: #{local_variables}"
end

class Bear
  def initialize(pr)
    # the program's scope has changed since the proc was defined
    # but the proc still has access to the same lexical environment
    # that existed when it was defined
    p pr.call
  end
end

Bear.new(pr) # => "self: main, local_variables: [:x, :y, :pr, :_]"

At the time the pr variable is defined, self points to main, and local_variables() equals [:x, :y, :pr, :_]. When the Bear class is initialized and the pr proc is called, the proc’s bindings are still the same as when it was originally defined. Since procs can be passed around as variables and retain the bindings that existed when the proc was originally defined, Ruby procs meet the computer science definition of a closure.

Additional reading:
http://www.elonflegenheimer.com/2012/07/08/understanding-ruby-closures.html
http://www.skorks.com/2010/05/closures-a-simple-explanation-using-ruby/
http://blog.mostof.it/why-ruby-part-two-blocks-and-closures/

Advertisements

2 thoughts on “Why Ruby Procs are Closures

  1. Pingback: Bypassing Ruby Scope Gates | Ruby/Rails Programming

  2. Pingback: Ruby’s Binding Class (binding objects) | Ruby/Rails Programming

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s