instance_eval && class_eval

A

Artur Merke

Hi,

I'm just studing some metaprogramming and came across some problems.
The following code:

####################
class D
instance_eval do
define_method("i_method") do
print "\nin i_method"
end
def ii_method
print "\nin ii_method"
end
end
class_eval do
define_method("c_method") do
print "\nin c_method"
end
def cc_method
print "\nin cc_method"
end
end
end

D.new.i_method
D.ii_method
D.new.c_method
D.new.cc_method

D.i_method
##################

results in

in i_method
in ii_method
in c_method
in cc_method
metaruby2.rb:163: undefined method `i_method' for D:Class (NoMethodE
rror)

so why is

D.i_method wrong and
D.new.i_method correct?

BTW, I know the right way of solving this, but I'm somehow missing
something which would explain it to me in a consitent manner

here the solution:
class D
(class << self; self; end).instance_eval do #class_eval also does
the job
define_method( :iii_method ) do
print "\nin iii_method"
end
end
end

D.iii_method

which works fine.

Artur
 
X

Xavier Noria

On Oct 21, 2006, at 12:55 PM, Artur Merke wrote:

define_method defines an instance method both in the instance_eval
and class_eval sections of your code. To be able to call

D.method

method needs to be a class instance method of D (i.e. a method of the
singleton class of D herself).

-- fxn
 
A

Artur Merke

Xavier said:
On Oct 21, 2006, at 12:55 PM, Artur Merke wrote:

define_method defines an instance method both in the instance_eval
and class_eval sections of your code. To be able to call

D.method

method needs to be a class instance method of D (i.e. a method of the
singleton class of D herself).
yes (see also my solution I provided at the end of my msg), but this
was not the question,

the question was (and still is), why(!)

def a
end

and

define_method:)a) do
end

behave differently in instance_eval (and not in class_eval and anywhere
else) ...

AHA

Artur
 
P

Phrogz

Artur said:
so why is
D.i_method wrong and
D.new.i_method correct?

I'm not surprised by that. I'm surprised that standard def...end syntax
inside instance_eval behaves differently from being in the class scope,
when the self object in both cases is the same.

irb(main):001:0> class Foo
irb(main):002:1> p "Defining aa in #{self}##{self.object_id}"
irb(main):003:1> def aa; p :aa; end
irb(main):004:1> instance_eval{
irb(main):005:2* p "Defining bb in #{self}##{self.object_id}"
irb(main):006:2> def bb; p :bb; end
irb(main):007:2> }
irb(main):008:1> end
"Defining aa in Foo#1699170"
"Defining bb in Foo#1699170"
=> nil
irb(main):009:0> Foo.new.aa
:aa
=> nil
irb(main):010:0> Foo.bb
:bb
=> nil
 
X

Xavier Noria

the question was (and still is), why(!)

def a
end

and

define_method:)a) do
end

behave differently in instance_eval (and not in class_eval and
anywhere
else) ...

Ah yes, I see it now. I join the question, a posteriori looks like
within instance_eval we are in the context of the singleton class of
D, because D.ii_method works. But puts self does not seem to output
that one there

irb(main):010:0> class D; instance_eval do; puts self; end; end
D
=> nil
irb(main):011:0> class D; puts (class << self; self; end); end
#<Class:D>
=> nil

so I don't understand it either.

-- fxn
 
T

ts

P> I'm not surprised by that. I'm surprised that standard def...end syntax
P> inside instance_eval behaves differently from being in the class scope,
P> when the self object in both cases is the same.

def is a keyword and it don't use self to know where the method must be
defined but it use an "internal" variable the "current" class.

P> irb(main):001:0> class Foo

here you have

self = current class = Foo

P> irb(main):002:1> p "Defining aa in #{self}##{self.object_id}"
P> irb(main):003:1> def aa; p :aa; end
P> irb(main):004:1> instance_eval{

in instance_eval you have

self = Foo
current class = Foo singleton class

P> irb(main):005:2* p "Defining bb in #{self}##{self.object_id}"
P> irb(main):006:2> def bb; p :bb; end


Guy Decoux
 
X

Xavier Noria

P> I'm not surprised by that. I'm surprised that standard def...end
syntax
P> inside instance_eval behaves differently from being in the class
scope,
P> when the self object in both cases is the same.

def is a keyword and it don't use self to know where the method
must be
defined but it use an "internal" variable the "current" class.

Good!

Is the existence of that "current" class vs self documented somewhere
or do you know it from the sources? Does it have a name in jargon?
What about the fact that instance_eval switches current to the
singleton class of self? I saw it works for objects which are not
classes as well (which is a redundant exercise to reinforce this):

class A
end

a = A.new
b = A.new

a.instance_eval do
def croak
puts "croak!"
end
end

a.croak
b.croak

gives

croak!
tmp/foo.rb:13: undefined method `croak' for #<A:0x1e6374>
(NoMethodError)

so the "current" class is the singleton class of the object a as well.

-- fxn
 
T

ts

X> Is the existence of that "current" class vs self documented somewhere
X> or do you know it from the sources? Does it have a name in jargon?

ruby_class : it's in the source, this mean that it's documented :)

X> What about the fact that instance_eval switches current to the
X> singleton class of self? I saw it works for objects which are not
X> classes as well (which is a redundant exercise to reinforce this):

Well a class can be seen as an object or as a class, i.e. with a class
you can define a singleton method or a method.

#instance_eval work with any object, and in this case a class is just an
object like any other and def will define a singleton method

#class_eval work only with classes (and modules) and in this case def will
define instance methods.


Guy Decoux
 

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,777
Messages
2,569,604
Members
45,227
Latest member
Daniella65

Latest Threads

Top