Instance_eval && class_eval

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

On Oct 21, 2006, at 12:55 PM, Artur M. 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

Xavier N. schrieb:

On Oct 21, 2006, at 12:55 PM, Artur M. 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

On Oct 21, 2006, at 2:45 PM, Artur M. wrote:

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

Artur M. wrote:

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

“P” == Phrogz [email protected] writes:

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

On Oct 21, 2006, at 3:40 PM, ts wrote:

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

“X” == Xavier N. [email protected] writes:

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 :slight_smile:

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