From: Peter Ertl Date: 2006-06-13T23:41:41+09:00 Subject: Re: Getting a list of aliases I am not sure if I get your question right... maybe this is what you need: require 'set' def acts_as_test TestClasses.get << self end class TestClasses @@test_classes = Set.new def self.get @@test_classes end end class TestMe acts_as_test end class TestMeToo acts_as_test end > TestClasses.get.inspect # -------- Original-Nachricht -------- Datum: Tue, 13 Jun 2006 23:19:51 +0900 Von: Daniel Berger An: ruby-talk@ruby-lang.org Betreff: Re: Getting a list of aliases > Ryan Davis wrote: > > > > On Jun 11, 2006, at 7:17 AM, Daniel Berger wrote: > > > >> Is there a way to get a list of instance method aliases somehow? > >> > >> # Hypothetical syntax > >> Array.instance_method_aliases # ['size', 'map', ...] > >> > >> If not, I think it would be a nice little bit of extra inspection I > >> could use in certain situations, like when I'm in irb and feeling too > >> lazy to look at the documentation. ;) > >> > >> Actually, this idea struck me when I tried to figure out just the > >> "core" methods for a given class and wanted to exclude the aliases. > >> At the time, I had to view the source code directly and count them. > >> This proved more difficult than I thought, because sometimes methods > >> would redefine functions with different names rather than use > >> rb_define_alias() in the source code. > >> > >> To give you an example of what I mean, in array.c the Array#map > >> function is not declared using rb_define_alias(), but is simply mapped > >> (no pun intended) to a different function: > >> > >> rb_define_method(rb_cArray, "collect", rb_ary_collect, 0); > >> rb_define_method(rb_cArray, "map", rb_ary_collect, 0); > > > > WARNING: this gets gross: > > > > It is a little less relevant with the core classes (seeing how they > > don't change very much), but easier to figure out what is aliased. You > > can use ParseTree to get the sexps for the class Array, and then it > > becomes pretty "obvious": > > > > ruby -I../RubyInline/dev:lib -rparse_tree -e 'class Array; alias :blah > > :map; end; p ParseTree.new.parse_tree(Array)' > > > > [[:class, :Array, :Object, ... > > [:defn, :blah, [:fbody, [:cfunc, 504080, 0]]], ... > > [:defn, :collect, [:cfunc, 504080, 0]], > > [:defn, :collect!, [:cfunc, 504206, 0]], ... > > [:defn, :map, [:cfunc, 504080, 0]], > > [:defn, :map!, [:cfunc, 504206, 0]], ... > > ]] > > > > So, with c-implemented functions, your :defn is pretty much just a > > pointer to the C-function. You can compare the addresses and see what's > > been aliased. Likewise, with a real alias to a :cfunc you can dig a bit > > deeper and see that it points to it properly. > > > > In the case of aliases on ruby methods, it gets harder: > > > > % ruby -I../RubyInline/dev:lib -rparse_tree -e 'class X; def y; end; > > alias :x :y; end; p ParseTree.new.parse_tree(X)' > > > > [[:class, :X, :Object, > > [:defn, :x, [:fbody, [:scope, [:block, [:args], [:nil]]]]], > > [:defn, :y, [:scope, [:block, [:args], [:nil]]]]]] > > > > So, while you can conclude that :fbody is a marker for an alias to > > SOMETHING, you can't tell what because it is already expanded. You > > should be able to either compare sexps or use some C to dig in and see > > that the implementations (nd_body pointer) have the same address. The > > code in question is: > > > >> st_insert(RCLASS(klass)->m_tbl, name, > >> (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), > >> orig->nd_noex)); > > > > so the addresses should be the same. (yes, either option is rather > icky). > > > > > > Very interesting Ryan, thank you. > > What do you think about adding an Object.aliases method, though? Or is > it just not worth the memory/speed hit? > > Dan