From: Daniel Berger Date: 2006-06-13T23:19:51+09:00 Subject: 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