in reply to Should one treat method name as input?

eval method:
BEGIN { for my $name (qw {slurp get}) { eval<<"TILL_HERE"; sub $name { print("This is $name\n"); } TILL_HERE } } slurp; get; __END__ This is slurp This is get
AUTOLOAD method:
sub slurp; sub get; sub AUTOLOAD { my ($func) = $main::AUTOLOAD =~ /.*::(.*)/; if ($func eq "slurp" || $func eq "get") { print("This is $func\n"); } } slurp; get; __END__ This is slurp This is get
Three sub method:
sub common { my ($name, @args) = @_; print("This is $name\n"); } sub slurp {common("slurp", @_)} sub get {common("get", @_)} slurp; get; __END__ This is slurp This is get

All methods have their pros and cons. Most people will find the last solution the cleanest. But, without doing the benchmarks, I expect the latter to be the least efficient, specially if you have a lot of arguments. The three sub method has the disadvantage that you will always do two subcalls, and calling a sub in Perl is costly. It will also mean copying of @_ (although you could pass a reference to slurp/gets @_ to common), which is expensive if @_ is large.

With the AUTOLOAD method no second sub is called, but additional work per sub-call is still performed (parsing of, and branching on the value of $AUTOLOAD). And using AUTOLOAD gets tricky in an OO environment, as it doesn't have native support to delegate calls it doesn't want to handle.

Leaves us the eval method. The disadvantage is that the code looks messier, and that you will end up with a larger op-code tree, as you will compile identical code twice. The advantage is that all the extra costs are done at compiletime - there is no runtime penalty at all.

So, what the best route is for you is only something you can decide. You have to balance between compile- and runtime efficiency, and "cleanness" of your code (which is subjective).

Replies are listed 'Best First'.
Re^2: Should one treat method name as input?
by Jenda (Abbot) on Jan 07, 2005 at 14:47 UTC

    The third solution is a good case for goto &sub:

    sub common { my ($name, @args) = @_; print("This is $name\n"); } sub slurp {unshift(@_,"slurp"); goto &common} sub get {unshift(@_,"get"); goto &common} slurp; get; __END__ This is slurp This is get
    This way if you carp() or croak() within common() you get better error message plus it's quicker.

    Jenda
    We'd like to help you learn to help yourself
    Look around you, all you see are sympathetic eyes
    Stroll around the grounds until you feel at home
       -- P. Simon in Mrs. Robinson

Re^2: Should one treat method name as input?
by Mutant (Priest) on Jan 07, 2005 at 16:21 UTC
    It might be worth noting, method #3 is certainly the 'classic' method, mainly because it's the only one most other languages support...