All the pretty evals

So, I’ve been kind of confused about all of the different ways of evaling
stuff; in particular, all the different ways to define methods in classes:

class Foo
def bar
"bar"
end
end

p Foo.new.bar # --> “bar”

…is just like…

class Foo
$binding = binding
end

eval ‘def bar; “bar”; end’, $binding

p Foo.new.bar # --> “bar”

…which is just like…

class Foo
end

Foo.module_eval ‘def bar; “bar”; end’

p Foo.new.bar # --> “bar”

…which is just like…

class Foo
end

Foo.module_eval {define_method(“bar”){“bar”}}

p Foo.new.bar # --> “bar”

So, am I right that those are all basically identical ways of doing the same
thing? Here’s something slightly different: extending only one object:

class Foo
end

foo = Foo.new

foo.instance_eval ‘def bar; “bar”; end’

p foo.bar # --> “bar”

…which is maybe the same as…

class Foo
end

foo = Foo.new

Is this the only way to get this class?

klass = class << foo; self; end

klass.module_eval ‘def bar; “bar”; end’

p foo.bar # --> “bar”

…however, the following does not work…

class Foo
end

foo = Foo.new

foo.instance_eval {define_method(“bar”){“bar”}}
NoMethodError: undefined method define_method' for #<Foo:0x400be61c> from (irb):4 from (irb):4:ininstance_eval’
from (irb):4:in `instance_eval’
from (irb):4

…Well, I understand why that didn’t work… I guess my question is, why
does…

foo.instance_eval ‘def bar; “bar”; end’

…work? What does that even mean? Also, why (in the last working snippet)
does foo.class give Foo, rather than klass?

Just trying to make sense of it all,

Chris

So, I’ve been kind of confused about all of the different ways of evaling
stuff; in particular, all the different ways to define methods in classes:

class Foo
def bar
“bar”
end
end

p Foo.new.bar # → “bar”

…is just like…

class Foo
$binding = binding
end

eval ‘def bar; “bar”; end’, $binding

p Foo.new.bar # → “bar”

…which is just like…

class Foo
end

Foo.module_eval ‘def bar; “bar”; end’

p Foo.new.bar # → “bar”

…which is just like…

class Foo
end

Foo.module_eval {define_method(“bar”){“bar”}}

p Foo.new.bar # → “bar”

Don’t forget
irb(main):001:0> class Foo
irb(main):002:1> end
nil
irb(main):003:0> Foo.instance_eval { define_method(“bar”) {“bar”} }
#Proc:0x402744d4
irb(main):004:0> p Foo.new.bar
“bar”
nil

So, am I right that those are all basically identical ways of doing the same
thing? Here’s something slightly different: extending only one object:

class Foo
end

foo = Foo.new

foo.instance_eval ‘def bar; “bar”; end’

p foo.bar # → “bar”

…which is maybe the same as…

class Foo
end

foo = Foo.new

Is this the only way to get this class?

AFAIK yes.

klass = class << foo; self; end

irb(main):005:0> foo = Foo.new
#Foo:0x4027044c
irb(main):006:0> klass = class << foo; self; end
Foo

At first it seems you cannot get the singleton class
irb(main):007:0> def foo.fubar
irb(main):008:1> “fubar”
irb(main):009:1> end
nil
irb(main):010:0> klass = class << foo; self; end
Foo

I would have expected something magical such as
#<Class 0lx4022fe98>

But anyway we’re getting
irb(main):023:0> klass.new.fubar
TypeError: can’t create instance of virtual class
from (irb):23:in `new’
from (irb):23
irb(main):024:0> klass.instance_methods
[“fubar”]
irb(main):025:0> klass.to_s
“Foo”

.to_s is a liar :slight_smile:

> klass.module_eval 'def bar; "bar"; end' > > p foo.bar # --> "bar" > > ...however, the following does not work... > > class Foo > end > > foo = Foo.new > > foo.instance_eval {define_method("bar"){"bar"}} > NoMethodError: undefined method `define_method' for # > from (irb):4 > from (irb):4:in `instance_eval' > from (irb):4:in `instance_eval' > from (irb):4

define_method belongs to Module, you’re calling it in an instance of
Foo…

…Well, I understand why that didn’t work… I guess my question is, why
does…

foo.instance_eval ‘def bar; “bar”; end’

…work? What does that even mean? Also, why (in the last working snippet)
does foo.class give Foo, rather than klass?

If ‘def’ were a method in Ruby, it’d belong to Module and you’d be
right, it wouldn’t work. But it’s handled at the syntactic level, so it
just works, and you’re defining a singleton method.

As for foo.class == Foo, it looks like #class (aka #type) returns the
Class the object was instanciated from, not the singleton class.
Otherwise you’d not be able to do ‘object.class.new’ or the like.

···

On Wed, Dec 11, 2002 at 02:05:53PM +0900, Chris Pine wrote:

Just trying to make sense of it all,

Chris


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

There are 3 kinds of people: those who can count & those who can’t.
– Unknown source

[snip]

Don’t forget
irb(main):001:0> class Foo
irb(main):002:1> end
nil
irb(main):003:0> Foo.instance_eval { define_method(“bar”) {“bar”} }
#Proc:0x402744d4
irb(main):004:0> p Foo.new.bar
“bar”
nil

···

----- Original Message -----
From: “Mauricio Fernández” batsman.geo@yahoo.com


Now this totally confuses me… So these two are the same

Foo.module_eval ‘def bar; “bar”; end’
Foo.module_eval {define_method(“bar”){“bar”}}

…but these two are different…

Foo.instance_eval ‘def bar; “bar”; end’
Foo.instance_eval {define_method(“bar”){“bar”}}

…since one defines a class method and the other defines an instance
method.

Clearly, I understand how these work (i.e. what these lines of code do);
I’m asking why they work (what the underlying principle and reasoning
behind these is).


[snip]

class Foo
end

foo = Foo.new

Is this the only way to get this class?

AFAIK yes.

klass = class << foo; self; end

irb(main):005:0> foo = Foo.new
#Foo:0x4027044c
irb(main):006:0> klass = class << foo; self; end
Foo

My irb gives something a little more clear:

irb(main):004:0> klass = class << foo; self; end
=> #<Class:#Foo:0x400be61c>


irb(main):023:0> klass.new.fubar
TypeError: can’t create instance of virtual class

Virtual class? I think this is what I am not understanding very clearly.


define_method belongs to Module, you’re calling it in an instance of
Foo…

…Well, I understand why that didn’t work…


Well, I understood why that didn’t work… :slight_smile:


I guess my question is, why does…

foo.instance_eval ‘def bar; “bar”; end’

…work? What does that even mean?


This is creating a virtual class, then? Why is there no way normal way to
get an object’s virtual class? Any method I can think of to do this was
inadvertently create a virtual class if there wasn’t one already, but I’d
prefer one which simply returns nil if there wasn’t one.


Also, why (in the last working snippet)
does foo.class give Foo, rather than klass?

As for foo.class == Foo, it looks like #class (aka #type) returns the
Class the object was instanciated from, not the singleton class.
Otherwise you’d not be able to do ‘object.class.new’ or the like.


Yes, I can see that. :slight_smile:

I’m asking how this sort of singleton class differs from ‘regular’
inheritance. What is the theory/rationale/model behind this?

(If I asked why there was a law against killing people, I wouldn’t feel my
question was answered if someone said, “Because, you see, killing is
illegal,” and then referred me to the specific law. I’d be looking for
something more like, “Because killing is wrong, and because making killing
illegal makes it illegal for others to kill you.”)

Thanks,

Chris

I'm asking how this sort of singleton class differs from 'regular'
inheritance.

a singleton class is a class which is associated with an unique object.

For example

   class A
   end

   a = A.new
   b = A.new

`a' and `b' has the same class

When you write

   class << a
      def tt
         "tt"
      end
   end

ruby create a singleton class which is associated only with `a', this will
give methods specifics to `a'. In my example `a' respond to #tt but not
`b'

If it was possible to create an instance from this singleton class, like

   klass = class << b; self; end
   c = klass.new

This will means that `b' *AND* `c' will have the same singleton class, and
this class can't be singleton (because it will be associated with 2
objects).

Guy Decoux

[snip]

Yes, I can see that. :slight_smile:

I’m asking how this sort of singleton class differs from ‘regular’
inheritance. What is the theory/rationale/model behind this?

A singleton class is by definition associated to a single object. If you
were given the possibility to instantiate singleton classes, that
wouldn’t hold any longer.

class A
end

a = A.new
klass = class << a; self; end
b = klass.new # in non-existent Ruby

def a.bar
“bar”
end

b.bar # ? work cause the singleton is shared OR fail
# cause another “singleton” was created

In the second case, Ruby would have to stack “singleton classes”, and
you can see it’d quite hard to track. Up to one singleton class per
method. GRR

Singleton classes allow us to define methods on a per-object basis.
This isn’t compatible with making them “instantiable”.

(If I asked why there was a law against killing people, I wouldn’t feel my
question was answered if someone said, “Because, you see, killing is
illegal,” and then referred me to the specific law. I’d be looking for
something more like, “Because killing is wrong, and because making killing
illegal makes it illegal for others to kill you.”)

I think the reason for not being able to “inherit” specific properties
of objects (since that’s what instantiating singleton classes would
mean) is that such things should be done on a class level. If some
property is generic enough that somebody might want to use it, we should
use a class of objects having that property, not take them from one
specific object.

You might find the following better: “because inheriting properties from
single objects is wrong, and making ‘singleton’ classes really
singleton makes it illegal for you to try it”

Then there are the matters of style and the YANGTNI thing, but I’m not
matz so I cannot really use these points.

BTW, something along the lines of ““instantiable” (not)singletons” would be
irb(main):001:0> class A
irb(main):002:1> end
nil
irb(main):003:0> B = A.clone
A
irb(main):004:0> a = A.new
#<A:0x402743f8>
irb(main):005:0> b = B.new
#<A:0x402725e4>
irb(main):006:0> class B
irb(main):007:1> def bar
irb(main):008:2> p “bar”
irb(main):009:2> end
irb(main):010:1> end
nil
irb(main):011:0> a.bar
NameError: undefined method `bar’ for #<A:0x402743f8>
from (irb):11
irb(main):012:0> b.bar
“bar”
nil

So you can add things to the cloned class without affecting other
objects, but you can inherit from it if you want to.
But of course what we really want then is ‘class B < A’ and not this
nonsense. You can take it as a reduction to absurd proof of why
‘“instantiable” singletons’ is meaningless :slight_smile:

···

On Thu, Dec 12, 2002 at 01:51:47AM +0900, Chris Pine wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

If Bill Gates is the Devil then Linus Torvalds must be the Messiah.
– Unknown source