Alien has asked for the wisdom of the Perl Monks concerning the following question:

I don't know if you guys know any ruby or not , but I'll explain what I want to achieve , the best way I can . Using the keyword alias in Ruby , you can define an alias for a method . For example :

module Kernel alias :old_puts :puts def puts(what) old_puts "new behaviour of puts" old_puts what end end

using the alias keyword , I can still access the old method,but I can also override puts , or any other method . If I try to use a glob in perl , or a coderef , I lose the first function . Is there any way to create an alias or take a reference to a function and keep using that code , even if the method it holds changes ?

Replies are listed 'Best First'.
Re: perl equivalent to ruby's alias
by ikegami (Patriarch) on Sep 25, 2008 at 19:56 UTC
    sub foo { print( "Hello World\n" ); } BEGIN { *bar = \&foo; } foo(); bar();

    The BEGIN is not necessary, but it can avoid problems.

    Update: Or to demonstrate your requirements:

    sub foo { print( "foo\n" ); } BEGIN { *bar = \&foo; } BEGIN { *foo = sub { print( "bar\n" ); }; } foo(); # bar bar(); # foo
Re: perl equivalent to ruby's alias
by JavaFan (Canon) on Sep 25, 2008 at 20:07 UTC
    There are different methods, but I prefer to use:
    no strict 'refs'; my $old_puts = *{"puts"}{CODE}; no warnings 'redefine'; *{"puts"} = sub { ... }; puts(); # "New" puts. &$old_puts(); # "Old" puts.
    I think Memoize uses a similar construct.
Re: perl equivalent to ruby's alias
by karavelov (Monk) on Sep 25, 2008 at 20:12 UTC

    Is this what you want?

    use strict; package A; sub new { my $class = shift; bless {}, $class; } sub test { "original test" } sub do_alias { my $self = shift; *test_alias = \&test; } sub redefine_alias { my $self = shift; *test_alias = sub {"new test"}; } package main; sub say { print @_,"\n" } my $a = new A; say $a->test(); # test $a->do_alias(); say $a->test_alias(); # test $a->redefine_alias(); say $a->test_alias(); # new_test say $a->test(); # test

    Best regards

Re: perl equivalent to ruby's alias
by moritz (Cardinal) on Sep 25, 2008 at 21:04 UTC
    Since nobody mentioned it so far: take a look at Data::Alias.
      I think Attribute::Alias might work better.
      sub foo :Alias(bar) { ... } # These both do the same thing. foo(); bar();

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      Does this really do what the poster wants? My impression was that Data::Alias is designed more to handle magic aliasing of scalars (possibly references), such as occurs in fors and subroutines, than to handle non-scalars such as subroutines. Of course, you can use
      alias *old_func = \&new_func,
      but I don't see what that gains over just
      *old_func = \&new_func.
      I searched the Data::Alias documentation for 'code' and 'function', but couldn't find anything indicating what I might be missing.
Re: perl equivalent to ruby's alias
by Anonymous Monk on Sep 25, 2008 at 19:55 UTC
    Why?
    my $what = \&what; local *what = sub {'new what'}; warn $what->(); warn what(); sub what { 'what' } __END__ what at - line 4. new what at - line 5.
    perltoot, perlobj, perlboot
Re: perl equivalent to ruby's alias
by Alien (Monk) on Sep 25, 2008 at 20:17 UTC
    All of your answers were really helpful. Thanks guys !
      Thats great, but there's better ways to solve this problem(ie subclass)