eval "foo = ‘bar’"
p local_variables #–> [“foo”]
p eval “foo” #–> "bar"
p foo #–> foo.rb:4: undefined local variable or method `foo’ for
#Object:0x2ac38ce0 (NameError)
Why can’t use foo variable directly?
Whereas in irb
irb
irb(main):001:0> eval “foo = ‘bar’”
“bar"
irb(main):002:0> p local_variables
[”_", “foo”]
nil
irb(main):003:0> p foo
"bar"
nil
eval "foo = 'bar'"
p local_variables #--> ["foo"]
p eval "foo" #--> "bar"
p foo #--> foo.rb:4: undefined local variable or method `foo' for
#<Object:0x2ac38ce0> (NameError)
Why can't use foo variable directly?
When ruby compile the script, it find `foo' at this time there is no local
variable defined (eval is not yet executed) and ruby think that you have
wanted to write `foo()', i.e. a call to the method #foo
At runtime, eval will create a local variable, but when ruby execute the
lines `p foo' it will try to call the method #foo, because this is what it
has compiled. Here an example
pigeon% cat b.rb
#!/usr/bin/ruby
def foo
"ruby has called #foo"
end
eval "foo = 'bar'"
p local_variables
p eval "foo"
p foo
pigeon%
pigeon% b.rb
["foo"]
"bar"
"ruby has called #foo"
pigeon%
When ruby compile the script, it find foo' at this time there is no local variable defined (eval is not yet executed) and ruby think that you have wanted to write foo()', i.e. a call to the method #foo
At runtime, eval will create a local variable, but when ruby execute the
lines `p foo’ it will try to call the method #foo, because this is what
it
has compiled. Here an example
I think the problem is that Ruby cannot distinguish local variable from
method by its name.
If method called with prefix ‘&’ or postfix ‘()’ , there is no such
confusion.
At runtime, eval will create a local variable, but when ruby execute the
lines `p foo’ it will try to call the method #foo, because this is what it
has compiled.
Then at least the error message is confusing, isn’t it?
p foo #–> foo.rb:4: undefined local variable or method `foo’ for
Olaf
···
–
Olaf Klischat | TU Berlin computer science
Oberfeldstrasse 132 |
12683 Berlin, Germany |
phone: +49 30 54986231 | e-mail: klischat@cs.tu-berlin.de
I think the problem is that Ruby cannot distinguish local variable from
method by its name.
It can when you make for example an assignement
a = 12 # ==> local variable
when it's not an assignement, then ruby search if it exist a local
variable with this name. If the local variable is not found (i.e. it has
not seen a line where this variable was assigned) then it's a method call.
With Rite, you'll have a warning for this
/* method call without arguments */ #if 0
/* Rite will warn this */
rb_warn("ambiguous identifier; %s() or self.%s is better for method call",
rb_id2name(id), rb_id2name(id)); #endif
at compile type no local variable with the name ‘foo’ was defined
at run time, no method with the name `foo’ was defined
The difference of compile and runtime is blurred (in my mind at least;-)
and may explain the difficulties some people (including myself) have in
understanding visibility rules of local variables.
For example, I find it curious that Ruby raises a NameError when a
variable name is used before being declared, even so the interpreter
seems to have complete knowledge of all local_variable (that are
and will be) declared in the current scope.
···
p local_variables
begin
x = (eval “foo”).nil? # doesn’t raises a NameError since foo' is declared # in the rescue clause p foo # raises a NameError since foo’ is not
declared yet.
rescue => mes
p mes
foo = ‘bar’
end
p x,foo
p local_variables
begin
x = eval “foo”
p foo
rescue => mes
p mes
foo = ‘bar’
end
p x,foo
[“x”, “mes”, “foo”]
#<NameError: undefined local variable or method `foo’ for
Then try it with 1.6.7 (but protect NameError in the rescue clause) and
see the result for `x’
Interesting (I just complied a 1.6 cvs branch), the result for the eval and
non-eval versions are actually the same (like a non-eval 1.7 version). Do
you consider the 1.7 behavior as a bug?
Interesting (I just complied a 1.6 cvs branch), the result for the eval and
non-eval versions are actually the same (like a non-eval 1.7 version). Do
you consider the 1.7 behavior as a bug?
Well, I must say that it can seems strange to have as result `true' or
`nil' when you execute the same code normally or in #eval