Another Run Time Evaluation Q:

I am fiddling around with the eval() function, and loading information at
runtime. The following works as expected:

$> ruby -e 'str = “def foo; 10; end”; eval(str); puts foo+1’
11

However, why does this not work?

$>ruby -e ‘str = “a = 2”; eval(str); puts a’
-e:1: undefined local variable or method `a’ for #Object:0x124b00
(NameError)

I know I can do something like ‘bar = eval(str)’ to get the value to which
str evaluates to, but I was hoping it would remember the variable name,
mostly because the string I am evaluating has more than one operation in it,
and the assignment only captures the last. Is this not possible? Thanks.

Matt

p.s. If I do the equivalent in IRB, it remembers the variable name.

irb(main):005:0> str = "a =2; b =3"
"a =2; b =3"
irb(main):006:0> eval(str)
3
irb(main):007:0> a
2
irb(main):008:0> b
3
irb(main):009:0>

···

MSN 8 helps eliminate e-mail viruses. Get 2 months FREE*.
http://join.msn.com/?page=features/virus

“Orion Hunter” orion2480@hotmail.com wrote in message

However, why does this not work?

I can answer this part. Please see “ri eval” output for more details:

 As of Ruby 1.8, local variables assigned within an eval are
 only available after the eval if they were defined at the outter
 scope before the eval executed. In this way eval has the same
 scoping rules as blocks.

$>ruby -e ‘str = “a = 2”; eval(str); puts a’
-e:1: undefined local variable or method `a’ for #Object:0x124b00
(NameError)

p.s. If I do the equivalent in IRB, it remembers the variable name.

I don’t know how irb manages to do it : some “binding” magic I guess.
Can experts shed some light please?

– shanko

“Orion Hunter” orion2480@hotmail.com schrieb im Newsbeitrag
news:BAY2-F7808xWI0AT2Jv00000db0@hotmail.com

I am fiddling around with the eval() function, and loading information
at
runtime. The following works as expected:

$> ruby -e ‘str = “def foo; 10; end”; eval(str); puts foo+1’
11

However, why does this not work?

$>ruby -e ‘str = “a = 2”; eval(str); puts a’
-e:1: undefined local variable or method `a’ for #Object:0x124b00
(NameError)

try this

$>ruby -e ‘str = “a = 2”; eval(str, binding); puts a’

You need to give the current context for locals, otherwise eval creates
its own scope.

robert

Invoking “Hunt & Thomas” Programming Ruby - (Addison Wesley Longman) …

Chapter: Interactive Ruby Shell
Section: Restrictions

[… Excellent description …]

IMO, Ruby’s behaviour conforms to PoMS in this area.
(L=Least, M=Most or Maximum).

  • I would call it ‘bonkers’ :@

printf(“ruby %s (%s) [%s]\n”, RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM)
#d=‘I refuse to uncomment this’
eval(‘d=10’)
p d rescue eval(‘d+1’)

eval(‘d=12’)
p d rescue eval(‘d+1’, TOPLEVEL_BINDING)
p d

#-> ruby 1.7.3 (2002-11-17) [i386-mswin32]
#-> 11
#-> 13
#-> rb31D4.TMP:8: undefined local variable or method `d’

for #Object:0x258d4c8 (NameError)

daz

···

“Shashank Date” sdate@everestkc.net wrote:

“Orion Hunter” orion2480@hotmail.com wrote in message

However, why does this not work?

I can answer this part. Please see “ri eval” output for more details:

 As of Ruby 1.8, local variables assigned within an eval are
 only available after the eval if they were defined at the outter
 scope before the eval executed. In this way eval has the same
 scoping rules as blocks.

$>ruby -e ‘str = “a = 2”; eval(str); puts a’
-e:1: undefined local variable or method `a’ for #Object:0x124b00
(NameError)

p.s. If I do the equivalent in IRB, it remembers the variable name.

I don’t know how irb manages to do it : some “binding” magic I guess.
Can experts shed some light please?

– shanko

“Robert Klemme” bob.news@gmx.net wrote in message

try this

$>ruby -e ‘str = “a = 2”; eval(str, binding); puts a’

C:\>ruby -ve 'str = "a=2"; eval(str,binding); puts a'
ruby 1.8.0 (2003-05-26) [i386-mswin32]
-e:1: undefined local variable or method `a' for main:Object (NameError)

C:\>ruby -ve 'str = "a=2"; eval(str,TOPLEVEL_BINDING); puts a'
ruby 1.8.0 (2003-05-26) [i386-mswin32]
-e:1: undefined local variable or method `a' for main:Object (NameError)

You need to give the current context for locals, otherwise eval creates
its own scope.

Simply doing that did not work. There must be some way … how else
could irb make it work ?

“daz” dooby@d10.karoo.co.uk wrote in message
[snip]

printf(“ruby %s (%s) [%s]\n”, RUBY_VERSION, RUBY_RELEASE_DATE,
RUBY_PLATFORM)
#d=‘I refuse to uncomment this’
eval(‘d=10’)
p d rescue eval(‘d+1’)

eval(‘d=12’)
p d rescue eval(‘d+1’, TOPLEVEL_BINDING)
p d

#-> ruby 1.7.3 (2002-11-17) [i386-mswin32]
#-> 11
#-> 13
#-> rb31D4.TMP:8: undefined local variable or method `d’

for #Object:0x258d4c8 (NameError)

Did not work like this for me using 1.8.0 preview 2.
I did not see 11 and 13 at all … just the error for undefined
local variable. :frowning:

Try this

    C:\>ruby -ve 'str = "a=2"; eval(str,binding); puts a'

svg% ruby -ve 'a=nil; str = "a=2"; eval(str,binding); puts a'
ruby 1.8.0 (2003-06-24) [i686-linux]
2
svg%

    C:\>ruby -ve 'str = "a=2"; eval(str,TOPLEVEL_BINDING); puts a'

svg% ruby -ve 'a=nil; str = "a=2"; eval(str,TOPLEVEL_BINDING); puts a'
ruby 1.8.0 (2003-06-24) [i686-linux]
2
svg%

Guy Decoux

Did not work like this for me using 1.8.0 preview 2.
I did not see 11 and 13 at all ... just the error for undefined
local variable. :frowning:

This is because they use an interactive ruby shell which display the value
of the last expression, try this

   printf("ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM)
   eval('d=10')
   p begin p d rescue eval('d+1') end

   eval('d=12')
   p begin p d rescue eval('d+1', TOPLEVEL_BINDING) end
   p d

Guy Decoux

“ts” decoux@moulon.inra.fr schrieb im Newsbeitrag
news:200306251325.h5PDP4K06015@moulon.inra.fr

Try this

C:\>ruby -ve 'str = "a=2"; eval(str,binding); puts a'

svg% ruby -ve ‘a=nil; str = “a=2”; eval(str,binding); puts a’
ruby 1.8.0 (2003-06-24) [i686-linux]
2
svg%

That’s cheating: you assign to a before the eval. :-))

This works, but is ugly:
ruby -e ‘str = “a=2”; eval(str,binding); puts eval(“a”,binding)’

Or:

ruby -e ‘b=binding; str = “a=2”; eval(str,b); puts eval(“a”,b)’

Though I’m still not satisfied…

robert

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

svg% ruby -ve ‘a=nil; str = “a=2”; eval(str,binding); puts a’
^^^^
Of course, by creating ‘a’ here, this has to work. I would like
to know how irb can make it work without pre-creation of “a”.

Thanks,
– shanko

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

This is because they use an interactive ruby shell which display the
value
of the last expression, try this

[snip]

Yes, that worked !
Is that how it is done in irb then ?

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

svg% ruby -ve 'a=nil; str = "a=2"; eval(str,binding); puts a'

                           ^^^^
Of course, by creating 'a' here, this has to work. I would like
to know how irb can make it work without pre-creation of "a".

irb do someting like this

svg% ruby -e 'eval("a=2"); eval("puts a")'
2
svg%

My example work not because the variable was created before the eval, but
because ruby has seen *at compile time* that `a' is a variable.

If you write

   ruby -ve 'str = "a=2"; eval(str,binding); puts a'

at compile time, `puts a' is interpreted as a method call, i.e. `puts a()'

Now with

   ruby -ve 'a = nil; str = "a=2"; eval(str,binding); puts a'

when ruby compile the script, it see that `a' is a local variable and
`puts a' is interpreted as an access to the local variable `a'

Guy Decoux

My example work not because the variable was
created before the eval, but because ruby has
seen at compile time that `a’ is a variable.

If you write

ruby -ve ‘str = “a=2”; eval(str,binding); puts a’

at compile time, puts a' is interpreted as a method call, i.e. puts a()’

To further illustrate this point:

irb(main):001:0> VERSION
=> “1.6.8”
irb(main):002:0> str = “a = 2”; eval(str); puts a
NameError: undefined local variable or method `a’ for #Object:0x810fcd8
from (irb):2
irb(main):003:0> a
=> 2
irb(main):004:0>

- Warren Brown

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

irb do someting like this

svg% ruby -e ‘eval(“a=2”); eval(“puts a”)’
2

Oh, I see.

My example work not because the variable was created before the eval, but
because ruby has seen at compile time that `a’ is a variable.

If you write

ruby -ve ‘str = “a=2”; eval(str,binding); puts a’

at compile time, puts a' is interpreted as a method call, i.e. puts
a()’

Now with

ruby -ve ‘a = nil; str = “a=2”; eval(str,binding); puts a’

when ruby compile the script, it see that a' is a local variable and puts a’ is interpreted as an access to the local variable `a’

Got it ! Thanks for taking time to explain this in detail.

···

Guy Decoux