Eval in class method

Hi. I’m not seeing what I thought would happen with some eval code, here is
a sample via irb:

chandler@greyhound:~$ irb
irb(main):001:0> class FooBar
irb(main):002:1> def baz
irb(main):003:2> puts "foobar:baz"
irb(main):004:2> end
irb(main):005:1> end
nil
irb(main):006:0> f = FooBar.new
#FooBar:0x4027e828
irb(main):007:0> f.baz
foobar:baz
nil

OK. So far so good, simply made a test class and ran a method from it.

irb(main):009:0> eval(“class FooBar\ndef baz\nputs ‘foobar:new
baz’\nend\nend”)
nil
irb(main):010:0> f.baz
foobar:new baz
nil

OK. So far even better. Use eval to redefine method.

irb(main):011:0> class FooBar
irb(main):012:1> def rebaz
irb(main):013:2> eval(“class FooBar\ndef baz\nputs
’foobar:rebaz’\nend\nend”)
irb(main):014:2> end
irb(main):015:1> end
nil
irb(main):016:0> f.rebaz
nil

So far nothing seems amiss. Instead of doing eval from main script, wrote
rebaz method to do eval as instance method.

irb(main):017:0> f.baz
foobar:new baz
nil

Sigh. After calling #rebaz which I thought would have changed #baz, #baz
still acts the same-- even though, except for scope/context, the eval
statement was the same exact statement as I used before, where #baz did
change.

How can I write an instance method that will get the eval done the way I
thought it was going to work? I don’t want to eval dependent on FooBar
class, the eval might want to change a method in Gizmo or Widget class
instead. Eval just needs to happen from FooBar since that is the class
that will have the method to handle evaluation of new code. Any
suggestions?

Thanks for your help.

-michael

···

++++++++++++++++++++++++++++++++++++++++++
Michael C. Libby x@ichimunki.com
public key: http://www.ichimunki.com/public_key.txt
web site: http://www.ichimunki.com
++++++++++++++++++++++++++++++++++++++++++

batsman@kodos:~/src/rubylang$ cat class_eval.rb

class FooBar
def baz
puts "FooBar::baz"
end

def on_me
FooBar.class_eval <<-EOF
def baz
puts "Redefined FooBar::baz"
end
EOF
end

def on_another( aclass )
aclass.class_eval <<-EOF
def baz
puts "Redefined #{aclass.to_s}::baz"
end
EOF
end
end

class Bar
def baz
puts "Bar::baz"
end
end

f = FooBar.new
b = Bar.new
f.baz
b.baz
f.on_me
f.baz
f.on_another Bar
b.baz
batsman@kodos:~/src/rubylang$ ruby class_eval.rb
FooBar::baz
Bar::baz
Redefined FooBar::baz
Redefined Bar::baz
batsman@kodos:~/src/rubylang$

···

On Sat, Aug 24, 2002 at 09:22:41PM +0900, michael libby wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi. I’m not seeing what I thought would happen with some eval code, here is
a sample via irb:

chandler@greyhound:~$ irb
irb(main):001:0> class FooBar
irb(main):002:1> def baz
irb(main):003:2> puts "foobar:baz"
irb(main):004:2> end
irb(main):005:1> end
nil
irb(main):006:0> f = FooBar.new
#FooBar:0x4027e828
irb(main):007:0> f.baz
foobar:baz
nil

OK. So far so good, simply made a test class and ran a method from it.

irb(main):009:0> eval(“class FooBar\ndef baz\nputs ‘foobar:new
baz’\nend\nend”)
nil
irb(main):010:0> f.baz
foobar:new baz
nil

OK. So far even better. Use eval to redefine method.

irb(main):011:0> class FooBar
irb(main):012:1> def rebaz
irb(main):013:2> eval(“class FooBar\ndef baz\nputs
’foobar:rebaz’\nend\nend”)
irb(main):014:2> end
irb(main):015:1> end
nil
irb(main):016:0> f.rebaz
nil

So far nothing seems amiss. Instead of doing eval from main script, wrote
rebaz method to do eval as instance method.

irb(main):017:0> f.baz
foobar:new baz
nil

Sigh. After calling #rebaz which I thought would have changed #baz, #baz
still acts the same-- even though, except for scope/context, the eval
statement was the same exact statement as I used before, where #baz did
change.

How can I write an instance method that will get the eval done the way I
thought it was going to work? I don’t want to eval dependent on FooBar
class, the eval might want to change a method in Gizmo or Widget class
instead. Eval just needs to happen from FooBar since that is the class
that will have the method to handle evaluation of new code. Any
suggestions?


_ _

__ __ | | ___ _ __ ___ __ _ _ __
’_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

It’s easy to get on the internet and forget you have a life
– Topic on #LinuxGER

[answering my own question here…]

What I found to work as an alternative was to write a root level eval
function and call that from within the class:

#!/usr/bin/ruby -w
def root_eval(eval_string)
eval(eval_string)
end

class FooBar
def baz
puts "foobar:baz"
end

def rebaz(s)
root_eval(s)
end
end

f = FooBar.new
f.baz
f.rebaz(“class FooBar\ndef baz\nputs ‘foobar:bitz’\nend\nend”)
f.baz

Output:
chandler@greyhound:~/ruby$ ruby root_eval.rb
foobar:baz
(eval):2: warning: discarding old baz
foobar:bitz
chandler@greyhound:~/ruby$

Which is perfect! Now my text editor can edit and reload its own code
without a restart.

-michael

···

On Saturday 24 August 2002 07:22, michael libby wrote:

irb(main):011:0> class FooBar
irb(main):012:1> def rebaz
irb(main):013:2> eval(“class FooBar\ndef baz\nputs
’foobar:rebaz’\nend\nend”)
irb(main):014:2> end
irb(main):015:1> end
nil
irb(main):016:0> f.rebaz
nil

So far nothing seems amiss. Instead of doing eval from main script,
wrote rebaz method to do eval as instance method.

irb(main):017:0> f.baz
foobar:new baz
nil

Sigh. After calling #rebaz which I thought would have changed #baz, #baz
still acts the same-- even though, except for scope/context, the eval
statement was the same exact statement as I used before, where #baz did
change.

++++++++++++++++++++++++++++++++++++++++++
Michael C. Libby x@ichimunki.com
public key: http://www.ichimunki.com/public_key.txt
web site: http://www.ichimunki.com
++++++++++++++++++++++++++++++++++++++++++