Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How could I redefine a subroutine and keep the old one too?

Here's what I'd like to achieve:

sub first {
    print "this is original first";
}

*original_first = \&first;

sub first {
    print "this is first redefined";
}

original_first(); # i expect this to print "this is original first"
first() # i expect this to print "this is first redefined"

I thought that by saving the symbol for first, I'd be able to later call the original subroutine ( under the name original_first ) and to also be able to call first, and get the one redefined. However, if I call the original_first, I still get the "this is first redefined". What do I have to do to make this work?

like image 348
Geo Avatar asked Dec 03 '09 21:12

Geo


3 Answers

This should work as you expect:

sub first {
    print "this is original first";
}

*original_first = \&first;

*first = sub {
    print "this is first redefined";
};
like image 149
Lukáš Lalinský Avatar answered Nov 10 '22 10:11

Lukáš Lalinský


in your code, Perl interprets both sub declarations similar to this:

BEGIN {
    *first = sub { ... }
}

so both assignments to &first end up happening before saving the copy and calling the routines. the fix is to make the second declaration into a runtime assignment:

sub first {
    print "this is original first";
}

*original_first = \&first;

*first = sub {print "this is first redefined"};

original_first(); # prints "this is original first"
first();          # prints "this is first redefined"
like image 9
Eric Strom Avatar answered Nov 10 '22 11:11

Eric Strom


See the Hook::LexWrap module, which can handle all of that for you. If you don't want to use the module, just look at the source, which shows you exactly how to do it.

like image 1
brian d foy Avatar answered Nov 10 '22 12:11

brian d foy