Instance_eval/class_eval including/extending modules

Consider the following example:

module SomeModule
def some_method
puts “Some Method - #{self}”
end
end

class SomeClass
def self.metaclass
class << self; self; end
end
end

SomeClass.instance_eval {include SomeModule} # instance method
SomeClass.instance_eval {extend SomeModule} # singleton method (class
method)
SomeClass.metaclass.instance_eval {include SomeModule} # class method

Using instance_eval on SomeClass sets the “ghost class” to be the
current class, so using include shouldn’t put the methods on “ghost
class” instead of SomeClass (SomeClass class methods)? In this case
using instance_eval or class_eval has the same result, depending only if
we’re using include or extend.

AFAIK the “problem” has to do with value of self, because private
methods are invoked on self (default receiver), so using instance_eval
or class_eval won’t matter as self will be SomeClass in both cases.
That’s why calling include in instance_eval/class_eval on metaclass
(self is now the “ghost class”) is the same as using extend when self is
SomeClass.

I’m using Ruby 1.8.6 and at least to me this seems kind of a strange
behaviour because using def or define_method will have different results
if we use instance_eval. Does Ruby 1.9 maintains this behaviour?

In my humble opinion would make more sense if instance_eval/class_eval
maintain the same behaviour on all methods and not the “special”
behaviour on private methods. Can someone enlight me?

HI –

On Sun, 31 Aug 2008, Pedro S. wrote:

 class << self; self; end

class" instead of SomeClass (SomeClass class methods)? In this case
using instance_eval or class_eval has the same result, depending only if
we’re using include or extend.

I’m not sure what you mean by “ghost class”. I think that might be an
unnecessary extra term.

AFAIK the “problem” has to do with value of self, because private
methods are invoked on self (default receiver), so using instance_eval
or class_eval won’t matter as self will be SomeClass in both cases.
That’s why calling include in instance_eval/class_eval on metaclass
(self is now the “ghost class”) is the same as using extend when self is
SomeClass.

That’s true all the time: mixing a module into an object’s singleton
class is the same as extending the object with that module. In both
cases, the module gets inserted in the object’s method lookup path
between the singleton class and the original class.

I’m using Ruby 1.8.6 and at least to me this seems kind of a strange
behaviour because using def or define_method will have different results
if we use instance_eval. Does Ruby 1.9 maintains this behaviour?

Yes, and that’s really part of the point of having both instance_eval
and class_eval. I don’t think there’s any advantage to merging them
into one behavior. Just choose the one you need in a given case.

In my humble opinion would make more sense if instance_eval/class_eval
maintain the same behaviour on all methods and not the “special”
behaviour on private methods. Can someone enlight me?

I don’t really see the anomaly you’re seeing, but let me outline the
rules that are followed (which, in the case of instance_eval, have
nothing to do with whether or not the object is a class), and maybe
that will clear it up or at least simplify it.

obj.instance_eval {…} sets self to obj during the block. Instance
methods defined in the block are singleton methods of obj (i.e.,
instance methods of obj’s singleton class).

c.class_eval sets self to c during the block. Instance methods defined
in the block are instance methods of c.

I think everything you’re seeing can be accounted for by those rules.

David

David, thanks for your reply.

I’m not sure what you mean by “ghost class”. I think that might be an
unnecessary extra term.

What I meant by “ghost class” was singleton class or eigenclass. I’ve
already seen different names for the class that Ruby creates when we use
instance_eval or define singleton methods.

Yes, and that’s really part of the point of having both instance_eval
and class_eval. I don’t think there’s any advantage to merging them
into one behavior. Just choose the one you need in a given case.

I’m not saying they should have the same behaviour in that sense, I was
trying to say that they should have the same behaviour no matter what is
the method visibility - private vs others. As matter of fact I think
using instance_eval or class_eval with include/extend should have
different results.

SomeClass.instance_eval {include SomeModule} has the same result as
SomeClass.class_eval {include SomeModule}

I don’t really see the anomaly you’re seeing, but let me outline the
rules that are followed (which, in the case of instance_eval, have
nothing to do with whether or not the object is a class), and maybe
that will clear it up or at least simplify it.

The example above showed me the “special case” between private methods
and other methods. Let me see if I can write an example that shows what
I’m trying to say. I think the best way is using def vs define_method.

SomeClass.instance_eval { def class_method; puts “Class Method”; end }
SomeClass.instance_eval do
define_method(:instance_method) {puts “Instance Method”}
end

SomeClass.class_method
SomeClass.new.instance_method

At least for me this is not something I would expect. When I define a
method using instance_eval I expect to have a singleton method (class
method in this case). The problem here has to do with self and what is
the current class, self is still SomeClass so define_method creates an
instance method, but because current class is the singleton class, using
def is the same as creating a class method. I guess this happen because
define_method is a private method. So in my opinion private methods have
different treatment from regular methods.

I hope I expressed myself in the right manner what I was trying to say
(i’m not a native english speaker, portuguese actually :p). If you could
tell me what you think about that I’ll appreciate that.

Hi –

On Mon, 1 Sep 2008, Pedro S. wrote:

and class_eval. I don’t think there’s any advantage to merging them

SomeClass.instance_eval do
instance method, but because current class is the singleton class, using
def is the same as creating a class method. I guess this happen because
define_method is a private method. So in my opinion private methods have
different treatment from regular methods.

I hope I expressed myself in the right manner what I was trying to say
(i’m not a native english speaker, portuguese actually :p). If you could
tell me what you think about that I’ll appreciate that.

I don’t think there’s any special case for private methods. They get
called on ‘self’, just as they always do. And if you instance_eval a
class, “def” does exactly what it does when you instance_eval any
object: it creates a singleton method.

Keep in mind that so-called “class methods” are essentially just
singleton methods of instances of Class. (The only special case
behavior is the fact that subclasses of class C can call class C’s
class methods.)

Like most questions in Ruby, it comes down to: classes are objects too
:slight_smile: I don’t think instance_eval does anything special with classes.
The only special thing you’d want to do is to be able to create
instance methods, and class_eval handles that case.

David

Thanks once again for the fast reply,

I don’t think there’s any special case for private methods. They get
called on ‘self’, just as they always do. And if you instance_eval a
class, “def” does exactly what it does when you instance_eval any
object: it creates a singleton method.

In my opinion define_method and def executed in the same context should
have the same behaviour, but they don’t. The reason def creates a
singleton method is because the current class is set to the singleton
class so there’s where the method will be defined, but self remains the
instance_eval receiver.

Keep in mind that so-called “class methods” are essentially just
singleton methods of instances of Class. (The only special case
behavior is the fact that subclasses of class C can call class C’s
class methods.)

I know that, that’s why I said singleton methods (class methods).

Like most questions in Ruby, it comes down to: classes are objects too
:slight_smile: I don’t think instance_eval does anything special with classes.
The only special thing you’d want to do is to be able to create
instance methods, and class_eval handles that case.

I guess I was unable to express correctly my point. I know that
class_eval lets create instance methods (that’s why the receiver must be
a class) and instance_eval singleton methods (on classes means class
methods). My problem is having instance_eval with def creating singleton
methods but with define_method creating instance methods. I expected to
have def and define_method to have the same result on the same context,
but they don’t.

Hi –

On Mon, 1 Sep 2008, Pedro S. wrote:

class so there’s where the method will be defined, but self remains the
instance_eval receiver.

Yes, that’s the rule, and it’s followed for all objects. It sounds
like you want a special case for instance_eval on class objects, so
that they somehow don’t realize that define_method is being called on
them, and I don’t think that’s a good idea. It’s better to keep the
definition of the instance_eval context consistent: self is swapped to
the receiver, and ‘def’ applies to the receiver’s singleton class.
That accounts for everything that currently happens, and it makes no
difference whether it’s a class object or some other object.

instance methods, and class_eval handles that case.

I guess I was unable to express correctly my point. I know that
class_eval lets create instance methods (that’s why the receiver must be
a class) and instance_eval singleton methods (on classes means class
methods). My problem is having instance_eval with def creating singleton
methods but with define_method creating instance methods. I expected to
have def and define_method to have the same result on the same context,
but they don’t.

I understand your point, but I don’t like the idea of introducing the
special case. Remember that the point of define_method is that it’s a
method, with method semantics and local scope in its code-block. It’s
not supposed to be identical to def, and it has very different uses.

For the case where self is the class and define_method and def behave
similarly, there’s class_eval. Instead of having instance_eval treat
classes as a special case, which would be inconsistent and confusing,
there’s a separate method for doing something very similar to a
‘class’ block, but with a code block.

David

Really fast this time. :wink:

For the case where self is the class and define_method and def behave
similarly, there’s class_eval. Instead of having instance_eval treat
classes as a special case, which would be inconsistent and confusing,
there’s a separate method for doing something very similar to a
‘class’ block, but with a code block.

I understand, I guess I can’t distinguish very well self from current
class concept. Can you explain the difference?

One last question to see if I understand all this correctly. Private
methods are invoked on self, other non-private methods are invoked on
current class?

I must say that I also find the difference between
instance_eval/class_eval and include/extend extremely confusing.

If someone clearly knows the fundamental rules, please please share.

Here’s my understanding:

def myMethod; end
-creates a method “myMethod” callable by instances of self.

Here’s a list of situations that I’m having trouble with:

  1. class Klass
    def myMethod; end
    end

-self is equal to Klass
-so myMethod() is callable by Klass.new

  1. Klass.instance_eval {def myMethod; end}

-self is equal to Klass
-so myMethod() is callable by Klass.new <-- this isn’t true

What’s wrong with my understanding? I think I’m not understanding def
correctly.

On Aug 31, 2008, at 9:15 PM, Patrick Li wrote:

Here’s a list of situations that I’m having trouble with:
-self is equal to Klass
-so myMethod() is callable by Klass.new <-- this isn’t true

What’s wrong with my understanding? I think I’m not understanding def
correctly.

Ruby has two separate concepts: self, the current object, and ‘the
current class’, which isn’t represented by an externally visible
variable. Methods are stored in the later, independent of the value of
self. It is confusing, but you can always remember that class_eval
creates instance methods and instance_eval creates class methods.
There are actually good reasons why this is so.

If you want to get deeper into this, I could recommend a certain
set of screencasts…

Dave

Ahhh… now it comes together. Thank you so much.

so here’s a quick revision of my understanding:

I’m gonna call the ‘the current class’ selfClass.

class Klass
<-- self is Klass
<-- selfClass is also Klass
end

def myMethod; end <-- creates myMethod(), callable by selfClass.new

obj.instance_eval <-- sets self to obj, sets selfClass to obj’s
metaclass

obj.class_eval <-- sets self to obj, AND sets selfClass to obj

include myModule <-- evaluates the instructions in myModule, underneath
selfClass

extend myModule <-- evaluates the instructions in myModule, underneath
self

Does that seem correct now? Thanks for your help by the way. That’s
quite a bit more clear now.

On Aug 31, 2008, at 9:50 PM, Patrick Li wrote:

quite a bit more clear n
No evaluation takes place. The module is already “compiled”, and Ruby
simply links a proxy for that module in to the parent class chain for
either the class or metaclass. That way, module functionality is
shared between multiple classes/objects that include/extend the module.

Dave

Now that I have a firmer grasp on Ruby’s object system, is it possible
to combine some of these methods, so that they’re easier to understand?

Here’s some changes that can be made:

Let me know what you think
-Patrick

What it does:
Combines eval/instance_eval/class_eval into one consistent method
Combines include/extend into one consistent method

Changes:

eval(proc)
-eval is now a method of Object. This ALWAYS sets self to the receiver
object,

and then evaluates proc.

def myMethod
-def is now a method of Module. This creates a method named myMethod()
that

can be called by instances of the receiver.

Consequences: This means that if self is not a subclass of Module, you
cannot

call def. Instead I propose a metaclass method that returns an objects

metaclass.

So instead of:
obj.instance_eval do
def myMethod; end
end

you MUST do:
obj.metaclass.instance_eval do
def myMethod; end
end

include myModule
-becomes a method of Object. This method puts the method definitions in
myModule into the receiver object.

From: Patrick Li [mailto:[email protected]]

I must say that I also find the difference between

instance_eval/class_eval and include/extend extremely confusing.

If someone clearly knows the fundamental rules, please please share.

Here’s my understanding:

def myMethod; end

-creates a method “myMethod” callable by instances of self.

Here’s a list of situations that I’m having trouble with:

1) class Klass

def myMethod; end

end

-self is equal to Klass

-so myMethod() is callable by Klass.new

generally, callable by instances of Klass

2) Klass.instance_eval {def myMethod; end}

-self is equal to Klass

-so myMethod() is callable by Klass.new

no.
the instance here is Klass, not those created/instanciated w Klass.new.
So you are creating a class method for Klass. Remember, classes are
objects too, ergo there are class methods too.

What’s wrong with my understanding? I think I’m not understanding def

correctly.

observe eg,

class Klass
def mymethod; end
end
#=> nil

k=Klass.new
#=> #Klass:0x28e1ff0

k.mymethod
#=> nil

ok. fine.
let’s try the other way, ie instance_eval.

k.instance_eval{def mymethod3; end}
#=> nil

k.mymethod3
#=> nil

fine still.
now let us try it for Klass itself.

Klass.mymethod
NoMethodError: undefined method `mymethod’ for Klass:Class

oops :wink:
maybe, we can do it w mymethod3

Klass.mymethod3
NoMethodError: undefined method `mymethod3’ for Klass:Class

oops still :wink:

Ok. let us define a method that works only for Klass.

Klass.instance_eval{def mymethod2; end}
#=> nil

k.mymethod2
NoMethodError: undefined method `mymethod2’ for #Klass:0x28e1ff0

heheh, it does not work for instances/creations of Klass.
now, let us test it for Klass itself.

Klass.mymethod2
#=> nil

ah, we see.

hth.
kind regards -botp

HI –

On Mon, 1 Sep 2008, Patrick Li wrote:

What it does:
Combines eval/instance_eval/class_eval into one consistent method
Combines include/extend into one consistent method

It’s not right to say that these things are inconsistent. They’re all
different from each other, and they all do things that make sense and
are needed frequently. include and extend are related, but they’re not
in conflict; they’re complementary, and they both do extremely useful
things.

that

can be called by instances of the receiver.

Consequences: This means that if self is not a subclass of Module, you
cannot

call def. Instead I propose a metaclass method that returns an objects

metaclass.

Join the club :slight_smile: Well, I call it Object#singleton_class, but there’s
been a request pending for this method for years.

So instead of:
obj.instance_eval do
def myMethod; end
end

you MUST do:
obj.metaclass.instance_eval do
def myMethod; end
end

Why? What’s the advantage of taking away the current instance_eval
scenario?

include myModule
-becomes a method of Object. This method puts the method definitions in
myModule into the receiver object.

I think you’re trying to squeeze things together too tightly. Right
now they’re pretty well-engineered to handle the major use-cases and
not to overlap with each other. I’d recommend living with them a
little longer, and playing around with them a bit – I think you’ll
see that they’re all pulling their weight pretty well.

David

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs