I'm kind of confused about how scoping works in Ruby. Which Ruby scoping rules prevent the following code from printing out the value of x?
#!/usr/bin/ruby
x = 5
def test
puts "x = #{x}"
end
test # => undefined local variable or method `x' for main:Object
The equivalent Python script does print the value of x:
#!/usr/bin/python
x = 5
def test():
print "x = %s" % x
test() # => x = 5
This is so called "scope gate". There are three gates in ruby: definition of a method, a class or a module. Meaning that inside that definition locals from outer scope are not visible.
This is so because when scope changes, current set of bindings gets replaced by a new set of bindings and cannot be easily accessed.
See "Metaprogramming Ruby: Program Like the Ruby Pros" for more information.
See "Ruby classes, include, and scope" for more information about Ruby's scoping and scope gating.
There are a few ways to provide visibility to your test function. One is to make the variable an instance variable:
#!/usr/bin/ruby
@x = 5
def test
puts "x = #{@x}"
end
And another is to use a closure with lambda:
#!/usr/bin/ruby
x = 5
test = lambda do
puts "x = #{x}"
end
test.call
or Proc.new()
#!/usr/bin/ruby
x = 5
test = Proc.new do
puts "x = #{x}"
end
test.call
For the differences between lambda and Proc.new, see "When to use lambda, when to use Proc.new?".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With