Eval and local variable


(Park Heesob) #1

Hi,

in following script

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

Park Heesob.


(ts) #2

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%

Guy Decoux


(Park Heesob) #3

“ts” decoux@moulon.inra.fr wrote in message
news:200206050618.g556IXb01996@moulon.inra.fr

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 writefoo()’, 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.

Park Heesob.


(Olaf Klischat) #4

ts decoux@moulon.inra.fr writes:

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


(ts) #5

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

Guy Decoux


(Kent Dahl) #6

Park Heesob wrote:

If method called with prefix ‘&’ or postfix ‘()’ , there is no such
confusion.

When and why is a method called with prefix ‘&’? I haven’t seen this, so
now I’m confused.

···


([ Kent Dahl ]/)_ ~ [ http://www.stud.ntnu.no/~kentda/ ]/~
))_student
/(( _d L b_/ NTNU - graduate engineering - 4. year )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)


(ts) #7

Then at least the error message is confusing, isn't it?

p foo #--> foo.rb:4: undefined local variable or method `foo' for

Not for me, this mean that

   * at compile type no local variable with the name 'foo' was defined
   * at run time, no method with the name `foo' was defined

Guy Decoux


(Park Heesob) #8

Hi,

“Kent Dahl” kentda@stud.ntnu.no wrote in message
news:3CFDBFCF.2F20C142@stud.ntnu.no

Park Heesob wrote:

If method called with prefix ‘&’ or postfix ‘()’ , there is no such
confusion.

When and why is a method called with prefix ‘&’? I haven’t seen this, so
now I’m confused.

‘&’ is Perl’s prefix, not Ruby’s.
I metioned it just as an example.
Sorry for confusing :slight_smile:

Park Heesob.


(Christoph) #9

“ts” decoux@moulon.inra.fr wrote in message

Not for me, this mean that

since you understand whats going on anyway;-)

  • 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 sincefoo’ 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

#Object:0x100fb0a8>

true

“bar”


and for good measure the eval version …


eval %{
p local_variables

begin
x = (eval “foo”).nil? # already raises a NameError …
p foo
rescue => mes
p mes
foo = 'bar’
end

p x,foo # curiously this does not raise an `x’ NameError

}

results in

[]

#<NameError: (eval):1: undefined local variable or method `foo’ for

#Object:0x100fb0a8>

nil

“bar”


/Christoph


(ts) #10

and for good measure the eval version ...

You are using 1.7, no ?

:slight_smile:

Guy Decoux


(Christoph) #11

“ts” decoux@moulon.inra.fr wrote in

You are using 1.7, no ?

Yes …

/Christoph


(ts) #12

"ts" <decoux@moulon.inra.fr> wrote in
....

You are using 1.7, no ?

Yes ...

Then try it with 1.6.7 (but protect NameError in the rescue clause) and
see the result for `x'

Guy Decoux


(Christoph) #13

“ts” decoux@moulon.inra.fr wrote in message
news:200206061352.g56DqKl28946@moulon.inra.fr

“ts” decoux@moulon.inra.fr wrote in

You are using 1.7, no ?

Yes …

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?

/Christoph


(ts) #14

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

Guy Decoux


(Marcin 'Qrczak' Kowalczyk) #15

Fri, 7 Jun 2002 01:08:59 +0900, ts decoux@moulon.inra.fr pisze:

Well, I must say that it can seems strange to have as result true' ornil’ when you execute the same code normally or in #eval

For me eval is evil and static name resolving is preferable,
so I would rather aim at making eval unnecessary.

···


__("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/
__/
^^
QRCZAK