#method(false) returns singleton methods?

T

Trans

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"]
 
G

George Ogata

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 <[email protected]>

* 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... ;-)
 
T

Trans

George said:
It hasn't changed recently:

Tue May 6 14:39:36 2003 Yukihiro Matsumoto <[email protected]>

* 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.
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.
 
P

Peña, Botp

:From =3D> "Trans [mailto:[email protected]]"

# 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=20
# time ago, but
# I still agress with the idea of a sinlge interface that takes symbolic
# "filters".
#=20
# obj.methods:)singleton)
# obj.methods:)public)
# obj.methods:)all)
# obj.methods:)private, :public) # combination

+10
-botp
 
T

Trans

Pe=F1a said:
:From =3D> "Trans [mailto:[email protected]]"

# 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_inst=
ance_methods

t=2E
 
G

George Ogata

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? ;-)
 
T

Trans

George said:
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.
 
G

George Ogata

George said:
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. :-/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top