[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

#method(false) returns singleton methods?

Trans

11/29/2006 10:39:00 PM

I had a hard enough time recalling that #instance_methods only returns
public methods rather then all methods, and after all this time I'm
only now discovering that #methods(false) only returns singleton
methods? Why? Has it changed? Am I loosing my mind? The ri doumentation
fails even to metion the parameter. The asymmetry of these
method-methods continually wastes effort.

irb(main):001:0> class A
irb(main):002:1> def a; end
irb(main):003:1> private
irb(main):004:1> def b; end
irb(main):005:1> protected
irb(main):006:1> def c; end
irb(main):007:1> end
=> nil
irb(main):008:0> a = A.new
=> #<A:0xb7c9705c>
irb(main):009:0> def a.d; end
=> nil
irb(main):010:0> a.methods
=> ["to_a", "respond_to?", "type", "protected_methods", "eql?",
"instance_variable_set", "is_a?", "hash", "to_s", "send", "class",
"tainted?", "private_methods", "__send__", "untaint", "a", "id",
"inspect", "instance_eval", "clone", "public_methods", "extend",
"freeze", "display", "__id__", "d", "==", "methods", "method", "===",
"nil?", "dup", "instance_variables", "instance_of?", "object_id", "=~",
"c", "singleton_methods", "equal?", "taint", "frozen?",
"instance_variable_get", "kind_of?"]
irb(main):011:0> a.methods(false)
=> ["d"]

7 Answers

George

11/30/2006 4:42:00 AM

0

On 11/30/06, Trans <transfire@gmail.com> wrote:
> I had a hard enough time recalling that #instance_methods only returns
> public methods rather then all methods, and after all this time I'm
> only now discovering that #methods(false) only returns singleton
> methods? Why? Has it changed? Am I loosing my mind?

It hasn't changed recently:

Tue May 6 14:39:36 2003 Yukihiro Matsumoto <matz@ruby-lang.org>

* object.c (rb_obj_methods): list singleton methods if recur
argument is false; list all methods otherwise.

> The ri doumentation fails even to metion the parameter.

You're right. I reckon a documentation patch would be well-appreciated... ;-)

Trans

11/30/2006 5:15:00 PM

0


George Ogata wrote:
> On 11/30/06, Trans <transfire@gmail.com> wrote:
> > I had a hard enough time recalling that #instance_methods only returns
> > public methods rather then all methods, and after all this time I'm
> > only now discovering that #methods(false) only returns singleton
> > methods? Why? Has it changed? Am I loosing my mind?
>
> It hasn't changed recently:
>
> Tue May 6 14:39:36 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
>
> * object.c (rb_obj_methods): list singleton methods if recur
> argument is false; list all methods otherwise.

Thanks. I suppose matz has his reasons. Though I can't say I quite
phatom them. Even his changelog entry isn;t exactly corrent since only
_public_ singleton methods show up if argument is false; and list all
_public_ methods otherwise.

I have to agree with David Black that this true false parameter has no
sematic quality. That is differs in result from obj.methods to
class.methods is further confusing on top of the distinctions between
methods, public_methods, etc. This was brought up a long time ago, but
I still agress with the idea of a sinlge interface that takes symbolic
"filters".

obj.methods(:singleton)
obj.methods(:public)
obj.methods(:all)
obj.methods(:private, :public) # combination

etc.

> > The ri doumentation fails even to metion the parameter.

> You're right. I reckon a documentation patch would be well-appreciated... ;-)

Hehe. Well, that's going to have be left up to one of our doc
specialists. I already have enough cod eof my own that need
documenting. :-)

T.

Peña, Botp

12/4/2006 4:02:00 AM

0

:From => "Trans [mailto:transfire@gmail.com]"

# I have to agree with David Black that this true false parameter has no
# sematic quality. That is differs in result from obj.methods to
# class.methods is further confusing on top of the distinctions between
# methods, public_methods, etc. This was brought up a long
# time ago, but
# I still agress with the idea of a sinlge interface that takes symbolic
# "filters".
#
# obj.methods(:singleton)
# obj.methods(:public)
# obj.methods(:all)
# obj.methods(:private, :public) # combination

+10
-botp

Trans

12/8/2006 2:41:00 PM

0


Peña wrote:
> :From => "Trans [mailto:transfire@gmail.com]"
>
> # I have to agree with David Black that this true false parameter has no
> # sematic quality. That is differs in result from obj.methods to
> # class.methods is further confusing on top of the distinctions between
> # methods, public_methods, etc. This was brought up a long
> # time ago, but
> # I still agress with the idea of a sinlge interface that takes symbolic
> # "filters".
> #
> # obj.methods(:singleton)
> # obj.methods(:public)
> # obj.methods(:all)
> # obj.methods(:private, :public) # combination
>
> +10

big up :-)

just to relate this to #each in the method mode var conversation. I can
understand matz steering clear of symbolic parameters on the whole, but
in this case I agree with your +10 assessment. It's just too fitting a
use case. the biggest case in point, how to gather all methods. this
blows:


mod.public_instance_methods+mod.private_instance_methods+mod.protected_instance_methods

t.


George

12/9/2006 7:22:00 AM

0

On 12/1/06, Trans <transfire@gmail.com> wrote:
>
> > On 11/30/06, Trans <transfire@gmail.com> wrote:
> Thanks. I suppose matz has his reasons. Though I can't say I quite
> phatom them. Even his changelog entry isn;t exactly corrent since only
> _public_ singleton methods show up if argument is false; and list all
> _public_ methods otherwise.

Almost right; it's actually _nonprivate_ methods. ;-) And yeah,
there's a peculiar asymmetry, between #methods and
#(public|protected|private)_methods in exactly what gets included,
even with the same argument. For example, #methods(false) only hits
the singleton class, but #public_methods(false) goes up the ancestor
chain to and including #class . In fact, #methods(false) is actually
equivalent to #singleton_methods(false), yet another #*_method method
with different boolean-parameter semantics. :-/

class B
def boo
end
end

class D < B
def doo
end
end

d = D.new

module M
def moo
end
end

class << d
include M
def scoo
end
end

# so ancestor chain is: #<Class:d> < M < D < B

d.methods.grep(/oo/) #=> ["boo", "scoo", "doo", "moo"]
d.methods(false).grep(/oo/) #=> ["scoo"]
d.public_methods.grep(/oo/) #=> ["boo", "scoo", "doo", "moo"]
d.public_methods(false).grep(/oo/) #=> ["doo", "scoo", "moo"]
d.singleton_methods.grep(/oo/) #=> ["scoo", "moo"]
d.singleton_methods(false).grep(/oo/) #=> ["scoo"]

> I have to agree with David Black that this true false parameter has no
> sematic quality. That is differs in result from obj.methods to
> class.methods is further confusing on top of the distinctions between
> methods, public_methods, etc. This was brought up a long time ago, but
> I still agress with the idea of a sinlge interface that takes symbolic
> "filters".
>
> obj.methods(:singleton)
> obj.methods(:public)
> obj.methods(:all)
> obj.methods(:private, :public) # combination
>
> etc.

I agree that the boolean parameter is not ideal. I'm not entirely
sold on your suggestion yet either, though. Firstly, I'm not so sure
:singleton belongs in there. I'd expect (:singleton, :public) to mean
"singleton AND public", whereas (:public, :private) looks more like
"public OR private", and mushing 'em all up feels a bit icky. This
still doesn't cover the current semantics of #singleton_methods(true),
either. Would we need another filter to mean "singleton with included
modules"?

The other bit of irkage I forsee with this is that presumably no args
would mean return [], which means you'd lose the convenience of
querying things usefully with plain old "thing.methods".

> Hehe. Well, that's going to have be left up to one of our doc
> specialists. I already have enough cod eof my own that need
> documenting. :-)

Well, I'd hardly label myself a "doc specialist", but if you won't, I
will. After all, what code could be more worth documenting than the
ruby core? ;-)

Trans

12/9/2006 10:42:00 PM

0


George Ogata wrote:
> On 12/1/06, Trans <transfire@gmail.com> wrote:
> >
> > > On 11/30/06, Trans <transfire@gmail.com> wrote:
> > Thanks. I suppose matz has his reasons. Though I can't say I quite
> > phatom them. Even his changelog entry isn;t exactly corrent since only
> > _public_ singleton methods show up if argument is false; and list all
> > _public_ methods otherwise.
>
> Almost right; it's actually _nonprivate_ methods. ;-) And yeah,
> there's a peculiar asymmetry, between #methods and
> #(public|protected|private)_methods in exactly what gets included,
> even with the same argument. For example, #methods(false) only hits
> the singleton class, but #public_methods(false) goes up the ancestor
> chain to and including #class . In fact, #methods(false) is actually
> equivalent to #singleton_methods(false), yet another #*_method method
> with different boolean-parameter semantics. :-/
>
> class B
> def boo
> end
> end
>
> class D < B
> def doo
> end
> end
>
> d = D.new
>
> module M
> def moo
> end
> end
>
> class << d
> include M
> def scoo
> end
> end
>
> # so ancestor chain is: #<Class:d> < M < D < B
>
> d.methods.grep(/oo/) #=> ["boo", "scoo", "doo", "moo"]
> d.methods(false).grep(/oo/) #=> ["scoo"]
> d.public_methods.grep(/oo/) #=> ["boo", "scoo", "doo", "moo"]
> d.public_methods(false).grep(/oo/) #=> ["doo", "scoo", "moo"]
> d.singleton_methods.grep(/oo/) #=> ["scoo", "moo"]
> d.singleton_methods(false).grep(/oo/) #=> ["scoo"]
>
> > I have to agree with David Black that this true false parameter has no
> > sematic quality. That is differs in result from obj.methods to
> > class.methods is further confusing on top of the distinctions between
> > methods, public_methods, etc. This was brought up a long time ago, but
> > I still agress with the idea of a sinlge interface that takes symbolic
> > "filters".
> >
> > obj.methods(:singleton)
> > obj.methods(:public)
> > obj.methods(:all)
> > obj.methods(:private, :public) # combination
> >
> > etc.
>
> I agree that the boolean parameter is not ideal. I'm not entirely
> sold on your suggestion yet either, though. Firstly, I'm not so sure
> :singleton belongs in there. I'd expect (:singleton, :public) to mean
> "singleton AND public", whereas (:public, :private) looks more like
> "public OR private", and mushing 'em all up feels a bit icky. This
> still doesn't cover the current semantics of #singleton_methods(true),
> either. Would we need another filter to mean "singleton with included
> modules"?
>
> The other bit of irkage I forsee with this is that presumably no args
> would mean return [], which means you'd lose the convenience of
> querying things usefully with plain old "thing.methods".

Good point about singleton, I suppose the easiest adjustment would be
:singleton_public, :singleton_private, :singleton_protected and
:singleton_all. Where :singleton itself could just be a synonym for
:singleton_public. Given how things currently work if no symbol is
given at all it would be the same as if just :public were given. That
would help a little with backwords compatability. Howerver there's
still the question of ancestor inclusion --and I suppose just adding
:ancestors would be enough for that.

Aside, it would be rather interesting if methods could be handled 1st
class. Then:

obj.methods.select{ |m| m.singleton? }
obj.methods.select{ |m| m.public? or m.private? }
obj.methods.select{ |m| m.inherited? }

> Well, I'd hardly label myself a "doc specialist", but if you won't, I
> will. After all, what code could be more worth documenting than the
> ruby core? ;-)

Do that and you will be! ;-) As for me, I just mean I don't have the
time.

t.


George

12/14/2006 1:48:00 AM

0

On 12/10/06, Trans <transfire@gmail.com> wrote:
> George Ogata wrote:
> > I agree that the boolean parameter is not ideal. I'm not entirely
> > sold on your suggestion yet either, though. Firstly, I'm not so sure
> > :singleton belongs in there. I'd expect (:singleton, :public) to mean
> > "singleton AND public", whereas (:public, :private) looks more like
> > "public OR private", and mushing 'em all up feels a bit icky. This
> > still doesn't cover the current semantics of #singleton_methods(true),
> > either. Would we need another filter to mean "singleton with included
> > modules"?
> >
> > The other bit of irkage I forsee with this is that presumably no args
> > would mean return [], which means you'd lose the convenience of
> > querying things usefully with plain old "thing.methods".
>
> Good point about singleton, I suppose the easiest adjustment would be
> :singleton_public, :singleton_private, :singleton_protected and
> :singleton_all.

Hmm, looks like a small combinatorial explosion. :-(

> Where :singleton itself could just be a synonym for
> :singleton_public. Given how things currently work if no symbol is
> given at all it would be the same as if just :public were given. That
> would help a little with backwords compatability. Howerver there's
> still the question of ancestor inclusion --and I suppose just adding
> :ancestors would be enough for that.

That's what I was kinda hoping to avoid--special cases. Some crazy
hacker's gonna be building the arg list programmatically one day, and
find they have to treat the empty list specially. I suppose you could
do something like:

def methods(visibilities=[:public, :protected], restriction=nil)
...
end

Or maaaybe:

def methods(*args)
if !args.empty? && args.all?{|a| a.respond_to?(:to_sym)}
visibilities = args.map{|a| a.to_sym}
restriction = nil
else
visibilities, restriction = *args
visibilities ||= [:public, :protected]
end
...
end

...where restriction would be things like :singleton and
:singleton_with_modules (or something--"ancestors" is too generic
IMHO; it strictly means just the modules included in the singleton
class, and nothing more), or nil for the whole ancestor chain.

But OTOH, it's starting to look a little scary now. Maybe I just need
time to let it sink in.

> Aside, it would be rather interesting if methods could be handled 1st
> class. Then:
>
> obj.methods.select{ |m| m.singleton? }
> obj.methods.select{ |m| m.public? or m.private? }
> obj.methods.select{ |m| m.inherited? }

Conceptually pleasing maybe, though quite verbose if all you want are
names. :-/