module_eval is an instance method?

7

7stud --

pickaxe2 lists module_eval as an instance method of Module. But:

num = 10
puts Object.module_eval('num')
---> 10

puts self
-->main

puts self.class
-->Object

puts self.module_eval('num')
undefined method `module_eval' for main:Object (NoMethodError)


1) Why am I able to call module_eval with a class name, i.e. Object?

2) Why can't I call module_eval with an instance of Object?
 
P

Paul McMahon

module_eval is a instance method of Module.

It is available to anything that is a Module.

irb(main):001:0> Object.is_a?(Module)
=3D> true
irb(main):002:0> String.is_a?(Module)
=3D> true
irb(main):003:0> self.is_a?(Module)
=3D> false
 
7

7stud --

Paul said:
module_eval is a instance method of Module.

It is available to anything that is a Module.

irb(main):001:0> Object.is_a?(Module)
=> true
irb(main):002:0> String.is_a?(Module)
=> true
irb(main):003:0> self.is_a?(Module)
=> false

Ok, how do you explain this output:

def meth1
Object.module_eval('num')
end

num = 10
Object.module_eval('num')
-->10

meth1
-->
`module_eval': undefined local variable or method `num' for Object:Class
(NameError)

According to pickaxe2, p. 393:

"When we define methods, we're actually creating (private) instance
methods for class Object."

What about top level variables?
 
M

MonkeeSage

Ok, how do you explain this output:
def meth1
Object.module_eval('num')
end

num = 10
Object.module_eval('num')
-->10

meth1
-->
`module_eval': undefined local variable or method `num' for Object:Class
(NameError)

num is not in the scope of meth1 or of the Object class so resolution
fails. If you use a global variable it works fine.

$num = 10
def meth1
Object.module_eval('$num')
end

Regards,
Jordan
 
M

MonkeeSage

Ps. You could also just use instance_eval...

$num = 10
def meth1
instance_eval('$num')
end
 
7

7stud --

Jordan said:
num is not in the scope of meth1 or of the Object class so resolution
fails. If you use a global variable it works fine.

It's not in the scope of the Object class? Then why does this work:

num = 10
Object.module_eval('num')
-->10
 
M

MonkeeSage

It's not in the scope of the Object class? Then why does this work:

num = 10
Object.module_eval('num')
-->10

According to the method resolution order (MRO), ruby looks for the
attribute in the local scope first, then in the containing scope which
is exposed to the local scope. So in this case, num is the in local
scope for Object#module_eval, i.e., the local scope is self (which is
"main"). If it's not in the local scope, then in this instance the
exposed containing scope is the Object class. Since 'num' is not in
the Object class, if you call Object.module_eval('num') w/o defining
num first, you get the same error. In other words, when you call
Object#module_eval from the top-level, the local scope is the top-
level. But when you call it from inside a function, the local scope is
the function. You can't access the higher scope of main from within
the lower scope of the function. To do that you need to use a global
variable, which exposes itself to all of the lower scopes of main.
Hmmm...I'm probably not explaining that very well. Basically, anything
you define in the top-level scope is only accessible from the top-
level scope. For nested scopes you either have to pass the data as a
parameter of the function, or use a global variable. Hope that makes
some sense. I'm tired, so forgive me if I'm being incoherent!

Regards,
Jordan
 
J

James Edward Gray II

Ok, how do you explain this output:

def meth1
Object.module_eval('num')
end

num = 10
Object.module_eval('num')
-->10

meth1
-->
`module_eval': undefined local variable or method `num' for
Object:Class
(NameError)

According to pickaxe2, p. 393:

"When we define methods, we're actually creating (private) instance
methods for class Object."

Ruby pretty much says exactly what's going here: num is not a local
variable or a method *accessible inside the scope of meth1.*
What about top level variables?

I don't reccomend this, but you can get at them:

#!/usr/bin/env ruby -wKU

def print_num
puts eval("num", TOPLEVEL_BINDING)
end

num = 10
print_num

__END__

James Edward Gray II
 

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,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top