Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why doesn't this python-like ruby script work?

Tags:

python

scope

ruby

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
like image 424
jvm_update Avatar asked Feb 19 '23 18:02

jvm_update


2 Answers

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.

like image 154
Sergio Tulentsev Avatar answered Mar 06 '23 06:03

Sergio Tulentsev


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?".

like image 45
Zach Avatar answered Mar 06 '23 04:03

Zach