[CHALLENGE] better alias_method

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

···

On 9/8/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

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

--
Rick DeNatale

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

Like is Haskell you'd have to explictily state it's recursive. So for
instance I'm suggesting:

  class A
    def x; "x"; end
  end

  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:

  class A
    def x(n); n - 1 ; end
  end

  class B < A
    def_rec x(n)
      x == 1 ? 1 : n + x(x(n)) # err... x(super(n))
    end
  end

Now in this case how do you call A#x from B#x if you need to? We would
still need to have #super as shown in the comment.

Hmm... better yet, you could do without super altogther and also not
need the special def_rec if we had a special method that meant "this
method", maybe #this. So:

  class B < A
    def x(n)
      x == 1 ? 1 : n + this(x(n))
    end
  end

Would work for the recursive case.

T.

···

On 9/8/06, Sylvain Joyeux <sylvain.joyeux@polytechnique.org> wrote:

> a = 1
> a = a + 1
>
> def a ; 1 ; end
> def a ; a + 1 ; end
>
> This would eliminate the need for #super except in cases of recursion,
> in which case a special notation is also needed for the definition. Eg.
> def_rec a, or something. But that's cool b/c it would be safer.

I don't see how you write "recursive methods which call super".

Ken Bloom wrote:

···

On Sat, 09 Sep 2006 02:54:35 +0900, Trans wrote:

> ara.t.howard@noaa.gov wrote:
>> heh. i think you may be hitting the same thing i was. here's some food for
>> thought:
>>
>>
>> this works:
>>
>> harp:~ > cat a.rb
>> class C
>> include Module.new{ def m() 'a' end }
>> include Module.new{ def m() super + 'b' end }
>> include Module.new{ def m() super + 'c' end }
>> end
>>
>> p C.new.m
>>
>>
>> harp:~ > ruby a.rb
>> "abc"
>>
>>
>> while this does not:
>>
>> harp:~ > cat a.rb
>> class C
>> def m() '' end
>>
>> include Module.new{ def m() super + 'a' end }
>> include Module.new{ def m() super + 'b' end }
>> include Module.new{ def m() super + 'c' end }
>> end
>>
>> p C.new.m
>>
>>
>> harp:~ > ruby a.rb
>> ""
>>
>> even more distilled:
>>
>> harp:~ > cat a.rb
>> class C
>> def m() '' end
>>
>> include Module.new{ def m() 'a' end }
>> end
>>
>> p C.new.m
>>
>>
>> harp:~ > ruby a.rb
>> ""
>>
>>
>> i find that behviour quite suprising... in fact, it seems like a bug, but i'm
>> probably wrong... thoughts?
>
> Not at all becasue inclusion adds to the inheritance chain, it doesn't
> inject methods. You can of course define an #inject method if you like.
> But it's still difficult to do the orginial intent of this thread b/c
> of how #super works.
>
> Personally I think it would cool if you could redefine a method calling
> on the previous definition just as one can redefine a variable calling
> on it's previous definition. Eg.
>
> a = 1
> a = a + 1
>
> def a ; 1 ; end
> def a ; a + 1 ; end
>
> This would eliminate the need for #super except in cases of recursion,
> in which case a special notation is also needed for the definition. Eg.
> 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.

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,

···

On 9/8/06, Ken Bloom <kbloom@gmail.com> 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.

--
Rick DeNatale

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

> a = 1
> a = a + 1
>
> def a ; 1 ; end
> def a ; a + 1 ; end
>
> This would eliminate the need for #super except in cases of recursion,
> in which case a special notation is also needed for the definition. Eg.
> def_rec a, or something. But that's cool b/c it would be safer.

I don't see how you write "recursive methods which call super".

Like is Haskell you'd have to explictily state it's recursive. So for
instance I'm suggesting:

class A
   def x; "x"; end
end

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.

class A
   def x(n); n - 1 ; end
end

class B < A
   def_rec x(n)
     x == 1 ? 1 : n + x(x(n)) # err... x(super(n))
   end
end

Now in this case how do you call A#x from B#x if you need to? We would
still need to have #super as shown in the comment.

Hmm... better yet, you could do without super altogther and also not
need the special def_rec if we had a special method that meant "this
method", maybe #this. So:

class B < A
   def x(n)
     x == 1 ? 1 : n + this(x(n))
   end
end

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

···

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

On 9/8/06, Sylvain Joyeux <sylvain.joyeux@polytechnique.org> wrote:

Would work for the recursive case.

T.