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
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
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) …
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 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> 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
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.
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
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.