Better alias_method

On Sep 8, 2006, at 5:58 PM, TRANS wrote:

definition. Eg.

class B < A
def x; x.upcase; end
end

Ordinarily B#x would recurse (and be an infinite loop). But not so in
my suggestion. So the above would work and rather you’d have to tell
it esspecially if recursion were desired, something like:

I’m pretty sure this would be impossible (also you are thinking of
ML, not Haskell (Haskell’s defs are recursive by default, it is in ML
where you have to say let rec (and Lisp/Scheme as well) to define a
recursive function) in ruby since ML and friends find those functions
lexically at compile time. I guess the parser could do the equivalent
of s/#{current_method}/super/g on the body of the function, but that
just makes it alternate syntax and doesn’t solve this problem.

Now in this case how do you call A#x from B#x if you need to? We would
end

Forth has this, it’s called “recurse” there. (also Joy has a whole
slew of words for recursion with anonymous functions).

On 9/8/06, [email protected] [email protected] wrote:

the primary reason to use aliases is not to simply have another handle on
names - but override or wrap a method for instance.

Here’s a sketch which generalizes this a little and adds a module
method sort of like private, which syncronizes the next method to be
defined.

I’m not sure how you’d make synchronized work like private and make
all subsequent methods synchronized. The issue is figuring out when to
turn it off when the module definition is closed.

rick@bill:/public/rubyscripts$ cat syncwrapper.rb
class Module

    alias_method "__method_added__", :method_added
    def method_added(meth_name)
            if @synchronize_new_method
                    @synchronize_new_method = false
                    synchronize_method(meth_name)
            end
            __method_added__(meth_name)
    end

    def synchronize_method(meth_name)
            module_eval {
                    alias_method "__#{meth_name}__", "#{meth_name}"
            }
            module_eval <<-code
                def #{meth_name}(*a, &b)
                   p "Synchronized"
                   __#{meth_name}__(*a, &b)
                end
               code
    end

    def synchronized(*meth_names)
            @synchronize_new_method = meth_names.empty?
            meth_names.each do |meth_name|
                    synchronize_method(meth_name)
            end
    end

end

class C

    def fee
            42
    end

    synchronized
    def fie
            43
    end

    def foe
            44
    end

    def fum
            45
    end

    synchronized :foe

end

p C.new.fee
p C.new.fie
p C.new.foe
p C.new.fum

rick@bill:/public/rubyscripts$ ruby syncwrapper.rb
42
“Synchronized”
43
“Synchronized”
44
45


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Ken B. wrote:

 class C

 end
 class C

on the previous definition just as one can redefine a variable calling
def_rec a, or something. But that’s cool b/c it would be safer.

In anycase, alternate solutions to the alias issue include
#wrap_method,

see Ruby Monitor-Functions - Or Meta-Meta-Programming in Ruby

#alias_chain, Matz’ :before and :after system (semi-aop) and cuts (aop).

Where is there information about these?

All of these can be found in Facets (facets.rubyforge.org) except Matz’
system which is just a concept given in his keynotes. (see
http://www.rubyist.net/~matz/slides/rc2005/mgp00006.html).

Note #alias_chain is actually #alias_method_chain and is borrowed from
Rails. It’s quite clever, but has limited usage.

T.

On Sat, 09 Sep 2006 00:20:51 +0900, ara.t.howard wrote:

the show stopper for me is the fact that define_method cannot define methods
that take blocks - so your approach loses them during the alias process.

i remember that define_method will soon have the ability to define methods
that take blocks do you know if that’s in 1.8.5 or the 1.9 branch?

Having established that 1.9 has this feature, my #override method (and
also Facets’ #wrap_method should Just Work ™ in 1.9 with defining
methods that take blocks.

–Ken

On 9/8/06, Ken B. [email protected] wrote:

The solution to this problem will actually let alias_method fall into
disuse faster, since we don’t need to use alias_method directly to wrap or
override an old method anymore.

But the point is that although you can ‘hide’ alias_method behind a
DSL or a layer of metaprogramming, having it as a language feature is
invaluable in creating DSLs or doing metaprogramming

Two more reasons for having aliased methods in Ruby is for comfort of
programmers coming from other languages, and to efficiently provide
identical methods some of which might be overriden in subclasses, and
show which shouldn’t be (like Object#==, and Object#===)

For an example of the first aliasing Enumerable#collect and
Enumerable#map gives Smalltalk programmers a familiar name for the
method, while map might be more familiar to others.

For the second,

Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/