module_eval differences between 1.8 & 1.9

F

Frederick Cheung

Consider the following:

module Foo
end

def do_stuff_to_foo(&block)
Foo.module_eval &block
end

In ruby 1.8 you can do something like this

do_stuff_to_foo {def greeting; 'hello'; end}
Foo.instance_methods #=> ['hello']

In ruby 1.9 however, no method is added to Foo, instead the method is
added to whoever called do_stuff_to_foo:

do_stuff_to_foo {def greeting; 'hello'; end}
Foo.instance_methods #=> []
greeting #=> 'hello'

Of course if you do
Foo.module_eval {def greeting; 'hello'; end}
then the method is added to Foo on both 1.8 & 1.9

I had a look through http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9
but I didn't see anything that seemed relevant.
Is this intended? Is there a way to write the do_stuff_to_foo method
in ruby 1.9 ?

Thanks,

Fred
 
F

Frederick Cheung

Consider the following:

module Foo
end

def do_stuff_to_foo(&block)
Foo.module_eval &block
end

In ruby 1.8 you can do something like this

do_stuff_to_foo {def greeting; 'hello'; end}
Foo.instance_methods #=> ['hello']
That should of course say
Foo.instance_methods #=> ["greeting"]
Sorry for the noise

Fred
 
M

MonkeeSage

Consider the following:

module Foo
end

def do_stuff_to_foo(&block)
Foo.module_eval &block
end

In ruby 1.8 you can do something like this

do_stuff_to_foo {def greeting; 'hello'; end}
Foo.instance_methods #=> ['hello']

In ruby 1.9 however, no method is added to Foo, instead the method is
added to whoever called do_stuff_to_foo:

do_stuff_to_foo {def greeting; 'hello'; end}
Foo.instance_methods #=> []
greeting #=> 'hello'

Of course if you do
Foo.module_eval {def greeting; 'hello'; end}
then the method is added to Foo on both 1.8 & 1.9

I had a look throughhttp://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9
but I didn't see anything that seemed relevant.
Is this intended? Is there a way to write the do_stuff_to_foo method
in ruby 1.9 ?

Thanks,

Fred

Apparently it only applies to the block version of #module_eval, the
string version seems to still work the same in 1.9.

module Foo; end
def do_stuff_to_foo(str)
Foo.module_eval str
end
do_stuff_to_foo %{def greeting; 'hello'; end}
p Foo.instance_methods #=> [:greeting]

Not sure why there's a difference in the block version.

Regards,
Jordan
 
M

MonkeeSage

Consider the following:

module Foo
end

def do_stuff_to_foo(&block)
Foo.module_eval &block
end

In ruby 1.8 you can do something like this

do_stuff_to_foo {def greeting; 'hello'; end}
Foo.instance_methods #=> ['hello']

In ruby 1.9 however, no method is added to Foo, instead the method is
added to whoever called do_stuff_to_foo:

do_stuff_to_foo {def greeting; 'hello'; end}
Foo.instance_methods #=> []
greeting #=> 'hello'

Of course if you do
Foo.module_eval {def greeting; 'hello'; end}
then the method is added to Foo on both 1.8 & 1.9

I had a look throughhttp://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9
but I didn't see anything that seemed relevant.
Is this intended? Is there a way to write the do_stuff_to_foo method
in ruby 1.9 ?

Thanks,

Fred

Played with this a bit today. It seems that #module_eval creates a
private instance method *and* a class method on module Foo, and also
creates a private instance method on main. And, as you noted, the
method is not listed under #instance_methods (or
#private_instance_methods for that matter; it's listed in
#private_methods). This seems really wrong to me (at the very least,
the block version should be consistent with the string version).

Here is the example, expanded to demonstrate what I'm referring to:

module Foo; end
class Bar; include Foo; end

def do_stuff_to_foo(&b)
Foo.module_eval &b
end

do_stuff_to_foo {def greet; "hello"; end}

p Foo.send:)greet) # => "hello"
p Bar.send:)greet) # => "hello"
p Bar.new.send:)greet) # => "hello"
p self.private_methods.include? :greet # => true

Ps. #module_exec is also broken like this.

Regards,
Jordan
 
F

Frederick Cheung

Played with this a bit today. It seems that #module_eval creates a
private instance method *and* a class method on module Foo, and also
creates a private instance method on main. And, as you noted, the
method is not listed under #instance_methods (or
#private_instance_methods for that matter; it's listed in
#private_methods). This seems really wrong to me (at the very least,
the block version should be consistent with the string version).
The private method stuff is a red herring - that's how things get
added to the top level.
Over on ruby-core Sasada Koichi said that he would fix it.

Fred
 
M

MonkeeSage

The private method stuff is a red herring - that's how things get
added to the top level.
Over on ruby-core Sasada Koichi said that he would fix it.

Fred

I didn't know that 1.9 had started making methods defined on main
private (not that it matters). Now if they will stop being randomly
added to main regardless of with what level of visibility, and
instance methods won't be turned into class methods, and so
forth... ;) Good to know it's being worked on.

Regards,
Jordan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top