0

(At least some kind of) Ruby code is accepted and evaluated within the default value specification of a method. In below, "foo" * 3 is evaluated:

def bar baz = "foo" * 3; baz end
bar # => "foofoofoo"

def bar baz: "foo" * 3; baz end
bar # => "foofoofoo"

However, when I try to evaluate a local variable/method under a certain scope in the default value description as follows, the local variable/method is evaluated under lexical scope:

MAIN = TOPLEVEL_BINDING.eval('self')
foo = 3

def bar baz = MAIN.instance_eval{foo}; end
bar # => undefined local variable or method `foo' for main:Object

def bar baz: MAIN.instance_eval{foo}; end
bar # => undefined local variable or method `foo' for main:Object
  • Why is foo above not evaluated within MAIN scope and is evaluated in lexical scope?
  • This seems there is some limitation to what Ruby expressions can be evaluated in the default value description. What exactly can be put there?
sawa
  • 165,429
  • 45
  • 277
  • 381

1 Answers1

1

foo is local variable for main. Your attempt to access local variable from outside might be shorten to:

▶ MAIN = TOPLEVEL_BINDING.eval('self')
▶ foo = 3
▶ MAIN.foo
#⇒ NoMethodError: undefined method `foo' for main:Object

The analogue of this code in less tangled manner is:

class A
  foo = 5
end

class B
  def a_foo
    A.new.foo
  end
end

▶ B.new.a_foo
#⇒ NoMethodError: undefined method `foo' for #<A:0x00000002293bd0>

If you want to provide access from the universe to your local variable you are to implement getter:

def MAIN.foo ; 5 ; end
def bar baz = MAIN.instance_eval{foo}; baz; end

▶ bar
#⇒ 5

Hope it helps.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160