[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

singleton methods vs. meta instance methods

Daniel DeLorme

12/13/2008 5:26:00 AM

If I understand the ruby object model correctly, then an object's
singleton methods are defined as the instance methods of that object's
meta/singleton class. So I tried to confirm this:

obj = Object.new
obj_meta = (class << obj;self;end)
def obj.foobar; end
obj.singleton_methods #=> ["foobar"]
obj_meta.instance_methods(false) #=> ["foobar"]

So far so good. But if I try the same thing with a class:

class A; end
A_meta = (class << A;self;end)
def A.foobar; end
A.singleton_methods #=> ["foobar"]
A_meta.instance_methods(false) #=> ["allocate", "superclass", "foobar",
"new"]

I understand why those 3 extra methods appear, but in that case
shouldn't they also appear as part of A.singleton_methods? Furthermore
this does not happen with builtin classes. Does anyone have an
explanation for what is going on here?

Daniel

14 Answers

Robert Dober

12/13/2008 7:46:00 PM

0

On Sat, Dec 13, 2008 at 6:25 AM, Daniel DeLorme <dan-ml@dan42.com> wrote:
> If I understand the ruby object model correctly, then an object's singlet=
on
> methods are defined as the instance methods of that object's meta/singlet=
on
> class. So I tried to confirm this:
>
> obj =3D Object.new
> obj_meta =3D (class << obj;self;end)
> def obj.foobar; end
> obj.singleton_methods #=3D> ["foobar"]
> obj_meta.instance_methods(false) #=3D> ["foobar"]
>
> So far so good. But if I try the same thing with a class:
>
> class A; end
> A_meta =3D (class << A;self;end)
> def A.foobar; end
> A.singleton_methods #=3D> ["foobar"]
> A_meta.instance_methods(false) #=3D> ["allocate", "superclass", "foobar",
> "new"]
>
> I understand why those 3 extra methods appear, but in that case shouldn't
> they also appear as part of A.singleton_methods? Furthermore this does no=
t
> happen with builtin classes. Does anyone have an explanation for what is
> going on here?
>
> Daniel
>
Daniel first, I had some difficulties to see what puzzles you. The
fact that meta methods are not singleton methods made perfectly sense,
but than I tried to define meta methods, which you did not, and then I
was as puzzled as you were ;)
----------------------------------------------- 8< ------------------------
507/15 > cat test1.rb && ruby test1.rb
#!/usr/bin/ruby
# vim: sw=3D2 ts=3D2 ft=3Druby expandtab tw=3D0 nu syn=3Don:
# file: test1.rb

def all_methods an_obj
p(
{ :name =3D> an_obj.name,
:meta =3D> class << an_obj; instance_methods( false ).sort end,
:single =3D> an_obj.singleton_methods( false ).sort }
)
end


def Object.answer; 42 end
def (A=3DClass::new).answer; 42 end
all_methods Object
all_methods A

class << Object; def almost; 41 end end
class << A; def almost; 41 end end
all_methods Object
all_methods A
{:meta=3D>["allocate", "answer", "new", "superclass"],
:single=3D>["answer"], :name=3D>"Object"}
{:meta=3D>["allocate", "answer", "new", "superclass"],
:single=3D>["answer"], :name=3D>"A"}
{:meta=3D>["allocate", "almost", "answer", "new", "superclass"],
:single=3D>["almost", "answer"], :name=3D>"Object"}
{:meta=3D>["allocate", "almost", "answer", "new", "superclass"],
:single=3D>["almost", "answer"], :name=3D>"A"}
------------------------------------------------ >8
---------------------------------------------------

So you are right it does not seem possible to create that kind of
diversity ourselves.
I could however not see the difference between A and Object, can you
explain please?

Cheers
Robert

>



--=20
Il computer non =E8 una macchina intelligente che aiuta le persone
stupide, anzi, =E8 una macchina stupida che funziona solo nelle mani
delle persone intelligenti.
Computers are not smart to help stupid people, rather they are stupid
and will work only if taken care of by smart people.

Umberto Eco

Brian Candler

12/13/2008 9:50:00 PM

0

Robert Dober wrote:
> I could however not see the difference between A and Object, can you
> explain please?

The OP used an *instance* of class Object, not Object itself, and
compared it with class A, which is an instance of class Class.

Perhaps it's clearer if written thus:

obj = Object.new
obj_meta = (class << obj;self;end)
def obj.foobar; end
p obj.singleton_methods #=> ["foobar"]
p obj_meta.instance_methods(false) #=> ["foobar"]

a = Class.new
a_meta = (class << a;self;end)
def a.foobar; end
p a.singleton_methods #=> ["foobar"]
p a_meta.instance_methods(false) #=> ["allocate", "superclass",
"foobar", "new"]

--
Posted via http://www.ruby-....

Brian Candler

12/13/2008 10:03:00 PM

0

Daniel DeLorme wrote:
> Furthermore this does not happen with builtin classes.

I'm not sure what you mean by that part. I get the same if I use String
instead of your class A:

a = String
a_meta = (class << a;self;end)
def a.foobar; end
p a.singleton_methods
p a_meta.instance_methods(false)

with 1.8.6p114 I get:
["foobar"]
["allocate", "foobar", "superclass", "new"]

with 1.9.1-preview2 I get:
[:try_convert, :foobar]
[:try_convert, :foobar, :allocate, :new, :superclass]

But notice what happens if I try an *instance* of String (which is
comparable to what you were doing with an *instance* of class Object)

a = String.new
a_meta = (class << a;self;end)
def a.foobar; end
p a.singleton_methods(false)
p a_meta.instance_methods(false)

["foobar"]
["split", "rstrip!", "to_sym", "swapcase", "chop", "foobar", "empty?",
"swapcase!", "to_f", "casecmp", "rindex", "intern", "tr", "to_s",
"reverse!", "strip!", "match", "hex", "each", "include?", "slice",
"next!", "*", "downcase!", "downcase", "sub", "+", "=~", "upto",
"concat", "lstrip", "each_byte", "succ!", "chop!", "size", "dump",
"rjust", "squeeze", "delete!", "eql?", "next", "reverse", "sub!",
"insert", "chomp", "[]", "inspect", "tr!", "replace", "[]=", "scan",
"tr_s", "lstrip!", "succ", "<<", "oct", "gsub", "capitalize!", "to_i",
"hash", "capitalize", "crypt", "index", "chomp!", "rstrip", "sum",
"upcase!", "center", "upcase", "count", "squeeze!", "unpack", "<=>",
"strip", "==", "length", "gsub!", "each_line", "slice!", "ljust",
"to_str", "%", "delete", "tr_s!"]

So you can see the instance methods of the object's metaclass include
the instance methods of that object's class. From one point of view this
seems reasonable to me; the metaclass is like a 'private subclass' to
the real class.

From another point of view, you might expect instance_methods(false) not
to return those methods. But I think that just explains why we have a
separate singleton_methods method - if you *really* want just the
singleton methods, not including the methods of the concrete class, call
that.

--
Posted via http://www.ruby-....

Daniel DeLorme

12/14/2008 10:52:00 AM

0

Brian Candler wrote:
> Daniel DeLorme wrote:
>> Furthermore this does not happen with builtin classes.
>
> I'm not sure what you mean by that part. I get the same if I use String
> instead of your class A:

You're right, I can't reproduce this anymore. It seems I got confused at
some point in my irb session.

> But notice what happens if I try an *instance* of String (which is
> comparable to what you were doing with an *instance* of class Object)
>
> a = String.new
> a_meta = (class << a;self;end)
> def a.foobar; end
> p a.singleton_methods(false)
> p a_meta.instance_methods(false)
>
> ["foobar"]
> ["split", "rstrip!", "to_sym", "swapcase", "chop", "foobar", "empty?",
[snip]
> "to_str", "%", "delete", "tr_s!"]
>
> So you can see the instance methods of the object's metaclass include
> the instance methods of that object's class. From one point of view this
> seems reasonable to me; the metaclass is like a 'private subclass' to
> the real class.
>
>>From another point of view, you might expect instance_methods(false) not
> to return those methods. But I think that just explains why we have a
> separate singleton_methods method - if you *really* want just the
> singleton methods, not including the methods of the concrete class, call
> that.

Thank you for the explanation, it does make a lot more sense now. I'm of
the second point of view; I would expect instance_methods(*true*) to
return those extra methods, but not instance_methods(*false*). But POLS
is relative, and now that I understand this behavior I can see why the
"allocate", "new" and "superclass" methods were present in A's singleton
class' instance methods; those are indeed the instance methods defined
in Class:
Class.instance_methods(false) #=> ["allocate", "superclass", "new"]

So it seems that
x.meta.instance_methods(false) == x.singleton_methods +
x.class.instance_methods(false)

I was missing that last part...

Daniel

Robert Dober

12/14/2008 10:56:00 AM

0

On Sat, Dec 13, 2008 at 10:50 PM, Brian Candler <b.candler@pobox.com> wrote=
:
> Robert Dober wrote:
>> I could however not see the difference between A and Object, can you
>> explain please?
>
> The OP used an *instance* of class Object, not Object itself, and
> compared it with class A, which is an instance of class Class.
Brian I referred to exactly the same thing you do in your next post,
just do a %s/Object/String/g.
I did see his first point, although he did not give an example for the
inconsistency.
Confusing is it not ;)
>
> Perhaps it's clearer if written thus:
>
> obj =3D Object.new
> obj_meta =3D (class << obj;self;end)
> def obj.foobar; end
> p obj.singleton_methods #=3D> ["foobar"]
> p obj_meta.instance_methods(false) #=3D> ["foobar"]
>
> a =3D Class.new
> a_meta =3D (class << a;self;end)
> def a.foobar; end
> p a.singleton_methods #=3D> ["foobar"]
> p a_meta.instance_methods(false) #=3D> ["allocate", "superclass",
> "foobar", "new"]
No really I feel up to here we are just fine, the problem starts when
we define something in the metaclass and
see it in the singleton class, thus we can ask ourself how is it
possible that we have the difference you showed in the last two lines.
>
> --
> Posted via http://www.ruby-....
>
>



--=20
Il computer non =E8 una macchina intelligente che aiuta le persone
stupide, anzi, =E8 una macchina stupida che funziona solo nelle mani
delle persone intelligenti.
Computers are not smart to help stupid people, rather they are stupid
and will work only if taken care of by smart people.

Umberto Eco

Robert Dober

12/14/2008 11:05:00 AM

0

On Sun, Dec 14, 2008 at 11:51 AM, Daniel DeLorme <dan-ml@dan42.com> wrote:

>>> From another point of view, you might expect instance_methods(false) no=
t
>>
>> to return those methods. But I think that just explains why we have a
>> separate singleton_methods method - if you *really* want just the single=
ton
>> methods, not including the methods of the concrete class, call that.
>
> Thank you for the explanation, it does make a lot more sense now.

Does it? I was of Brian's opinion until I added a method to the meta
class and it showed up in the singleton class, that definitely broke
this explanation and now I am really interested how this happens.
To be clear I am not surprised about what you have shown so far. I am
surprised that by adding a method to the metaclass it shows up in the
singleton!!!

So we are as confused as ever but I am certain that we are confused
about more important things and on a much higher level ;).

R.

--=20
Il computer non =E8 una macchina intelligente che aiuta le persone
stupide, anzi, =E8 una macchina stupida che funziona solo nelle mani
delle persone intelligenti.
Computers are not smart to help stupid people, rather they are stupid
and will work only if taken care of by smart people.

Umberto Eco

Brian Candler

12/14/2008 11:17:00 AM

0

Robert Dober wrote:
> On Sat, Dec 13, 2008 at 10:50 PM, Brian Candler <b.candler@pobox.com>
> wrote:
>> Robert Dober wrote:
>>> I could however not see the difference between A and Object, can you
>>> explain please?
>>
>> The OP used an *instance* of class Object, not Object itself, and
>> compared it with class A, which is an instance of class Class.
> Brian I referred to exactly the same thing you do in your next post,
> just do a %s/Object/String/g.

Maybe I overlooked something - all these classes and metaclasses can get
pretty confusing :-) I was comparing the part of your code where you
wrote:

def Object.answer; 42 end

with the OP's which had:

obj = Object.new
def obj.foobar; end

> No really I feel up to here we are just fine, the problem starts when
> we define something in the metaclass and
> see it in the singleton class

I'm not sure what the distinction is you're trying to make between
metaclass and singleton class. I believe they are two names for the same
thing.

The OP was trying to demonstrate that "an object's singleton methods are
defined as the instance methods of that object's meta/singleton class"

This was demonstrated successfully, given the additional info that
metaclass.instance_methods(false) returns both the instance methods in
the metaclass plus the instance methods of the actual class.

However, obj.singleton_methods returns only the instance methods in
obj.metaclass.

At least, that's how I understand it at the moment - I am happy to be
corrected if this is wrong.
--
Posted via http://www.ruby-....

Robert Dober

12/14/2008 11:36:00 AM

0

On Sun, Dec 14, 2008 at 12:16 PM, Brian Candler <b.candler@pobox.com> wrote=
:
<snip>
> This was demonstrated successfully, given the additional info that
> metaclass.instance_methods(false) returns both the instance methods in
> the metaclass plus the instance methods of the actual class.
>
> However, obj.singleton_methods returns only the instance methods in
> obj.metaclass.
Yes it comes down to this and hopefully you are right and I am wrong,
because I am getting headaches already ;).
But... alas
you say that a meta.instance_methods returns both instance methods in
the metaclass plus the instance methods
of the actual class. I agree, you have shown this, however, :new,
:allocate & :superclass are instance methods of the metaclass, not of
the actual class, or are they not?
This is for the example A
{:meta=3D>["allocate", "answer", "new", "superclass"],
:single=3D>["answer"], :name=3D>"A"}
new is defined in class << A,

no wait a moment it is not yet I guess I see the end of the light and
the beginning of the tunnel

def (A=3DClass::new).answer; 42 end
def A.new; allocate end
all_methods A
{:meta=3D>["allocate", "almost", "answer", ***"new"***, "superclass"],
:single=3D>["almost", "answer", ***"new"***], :name=3D>"A"}

Great job Brian I got it, thanx.
Cheers
Robert


>
> At least, that's how I understand it at the moment - I am happy to be
> corrected if this is wrong.
> --
> Posted via http://www.ruby-....
>
>



--=20
Il computer non =E8 una macchina intelligente che aiuta le persone
stupide, anzi, =E8 una macchina stupida che funziona solo nelle mani
delle persone intelligenti.
Computers are not smart to help stupid people, rather they are stupid
and will work only if taken care of by smart people.

Umberto Eco

David A. Black

12/14/2008 12:59:00 PM

0

Hi --

On Sun, 14 Dec 2008, Brian Candler wrote:

> Daniel DeLorme wrote:
>> Furthermore this does not happen with builtin classes.
>
> I'm not sure what you mean by that part. I get the same if I use String
> instead of your class A:
>
> a = String
> a_meta = (class << a;self;end)
> def a.foobar; end
> p a.singleton_methods
> p a_meta.instance_methods(false)
>
> with 1.8.6p114 I get:
> ["foobar"]
> ["allocate", "foobar", "superclass", "new"]
>
> with 1.9.1-preview2 I get:
> [:try_convert, :foobar]
> [:try_convert, :foobar, :allocate, :new, :superclass]
>
> But notice what happens if I try an *instance* of String (which is
> comparable to what you were doing with an *instance* of class Object)
>
> a = String.new
> a_meta = (class << a;self;end)
> def a.foobar; end
> p a.singleton_methods(false)
> p a_meta.instance_methods(false)
>
> ["foobar"]
> ["split", "rstrip!", "to_sym", "swapcase", "chop", "foobar", "empty?",
> "swapcase!", "to_f", "casecmp", "rindex", "intern", "tr", "to_s",
> "reverse!", "strip!", "match", "hex", "each", "include?", "slice",
> "next!", "*", "downcase!", "downcase", "sub", "+", "=~", "upto",
> "concat", "lstrip", "each_byte", "succ!", "chop!", "size", "dump",
> "rjust", "squeeze", "delete!", "eql?", "next", "reverse", "sub!",
> "insert", "chomp", "[]", "inspect", "tr!", "replace", "[]=", "scan",
> "tr_s", "lstrip!", "succ", "<<", "oct", "gsub", "capitalize!", "to_i",
> "hash", "capitalize", "crypt", "index", "chomp!", "rstrip", "sum",
> "upcase!", "center", "upcase", "count", "squeeze!", "unpack", "<=>",
> "strip", "==", "length", "gsub!", "each_line", "slice!", "ljust",
> "to_str", "%", "delete", "tr_s!"]
>
> So you can see the instance methods of the object's metaclass include
> the instance methods of that object's class. From one point of view this
> seems reasonable to me; the metaclass is like a 'private subclass' to
> the real class.
>
>> From another point of view, you might expect instance_methods(false) not
> to return those methods. But I think that just explains why we have a
> separate singleton_methods method - if you *really* want just the
> singleton methods, not including the methods of the concrete class, call
> that.

I've never liked the "false" flag thing, since it's obscure to begin
with. If it doesn't actually mean "defined in exactly this class",
then I'm not sure what purpose it serves at all.

(Don't mean to sound curmudgeonly -- am multi-tasking, which almost
always means I shouldn't post to ruby-talk since whatever the main
point is is probably zooming past me :-)


David

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS (Jan 12-15), Fort Lauderdale, FL
See http://www.r... for details
Coming in 2009: The Well-Grounded Rubyist (http://manning....)

Brian Candler

12/14/2008 1:14:00 PM

0

Robert Dober wrote:
> But... alas
> you say that a meta.instance_methods returns both instance methods in
> the metaclass plus the instance methods
> of the actual class. I agree, you have shown this, however, :new,
> :allocate & :superclass are instance methods of the metaclass, not of
> the actual class, or are they not?

I believe that they are instance methods of the actual class "Class".

irb(main):002:0> Class.instance_methods(false)
=> ["allocate", "superclass", "new"]
--
Posted via http://www.ruby-....