Bypassing Ruby Scope Gates (Flattening the Scope)

A Ruby program creates a new scope whenever it encounters a scope gate (the def, class, and module keywords). When a new scope is created, local variables from earlier scopes are not available, but the scope gates can be bypassed with closures. Read this blog post if you’re not familiar with Ruby’s scope gates.

The following code does not work because the class keyword creates a new scope:

# top level scope
x = 'bob'
class A # begin class scope
  puts x # => error
end # end class scope
# back in top level scope

The local variable x is defined in the top level scope (outer scope) and is not available in the class scope (inner scope). Ruby closures retain local variable bindings that are in place and can be used to bypass scope gates. Read this blog post if you’re not familiar with Ruby closures.

The Class.new closure captures all the top level local variable bindings and makes them available in the class definition.

# top level scope
x = 'bob'
A = Class.new do # begin closure
  puts x
end # end closure

Module#class_eval allows scope gates for existing classes to be bypassed.

class BBB; end
x = 'bob'
# use class_eval to bypass the scope gate for an existing class
BBB.class_eval do
  p x # => local variable is accessible
end

# local variables are not accessible when
# a class is reopened with the class keyword
class BBB
  p x # => error
end

Method scope gates are similar to class scope gates and can be bypassed with a closure:

class A # begin class scope
  x = 'bob'
  define_method :hi do # begin closure
    x
  end # end closure
end # end class scope
A.new.hi # => 'bob'

The define_method closure captures the class’s local variable bindings and makes them available to the hi() method.

Using closures to bypass scope gates is referred to as flattening the scope.

Advertisements

2 thoughts on “Bypassing Ruby Scope Gates (Flattening the Scope)

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