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

Hi All,
  I'm calling sub routines based on a couple of variables. At the moment I'm using eval, but I get the feeling there are other, probably more efficient ways of doing it.
my $subtext = "&subby${var1}_text_$var2();"; eval $subtext;
Thoughts?
I'm trying to keep things as efficient as possible so I'll be benchmarking every method we can come up with.

Lyle

Update: Thanks guys, I check these out and see what works best for me... Benchmarks show eval slowest by far. BrowserUK's fasterest, though I'll probably use TGI's dispatch table solution. Couldn't get rhesa's to work with benchmarks timethis??

Replies are listed 'Best First'.
Re: Calling subroutines based on variable names...
by TGI (Parson) on Apr 04, 2008 at 23:55 UTC

    Use a dispatch table:

    my @the_args = 0..5; my %functions = ( a => { x => \&sub_a_text_x, y => \&sub_a_text_y, }, b => { x => \&sub_b_text_x, y => \&sub_b_text_y, }, ); if( exists $functions{$var1} && exists $functions{$var1}{$var2} ) { $functions{$var1}{$var2}->(@the_args); } else { die "A horrible death"; }


    TGI says moo

Re: Calling subroutines based on variable names...
by rhesa (Vicar) on Apr 04, 2008 at 23:56 UTC
    dispatch tables are good for this sort of thing.

    An alternative to eval is pretending the name is a coderef:

    { no strict 'refs'; my $subname = "subby${var1}_text_${var2}"; $subname->(); }
    I'll leave the benchmarking to you.
Re: Calling subroutines based on variable names...
by BrowserUk (Patriarch) on Apr 04, 2008 at 23:54 UTC
Re: Calling subroutines based on variable names...
by dragonchild (Archbishop) on Apr 05, 2008 at 01:40 UTC
    rhesa's option about subrefs is a good one. However, someone people may squick at the no strict 'refs'; component. The following is strictures-compliant:
    my $obj = Some::Class->new( @args ); my $method = "sub_${x}_text_${y}"; my $rv = $obj->$method( @params );
    Yes, this is considered a feature.

    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?
Re: Calling subroutines based on variable names...
by repellent (Priest) on Apr 05, 2008 at 17:19 UTC
    Deciding symbolically which subroutine to call is not a robust implementation. You may be setting yourself (or someone else) up for difficult maintenance issues in the future.

    That's because you need to guarantee that $var1 and $var2 are always what you expect. Otherwise, as pointed out by TGI, you die "A horrible death";

    If you are able to guarantee $var1 and $var2, you'd be doing a dispatch table. But then, dispatch tables are not that easy to maintain. Who knows, you may require $var3 in the future?

    Notice how the keys of the dispatch table can be brought in as arguments for a generic function subby($var1, $var2, ...) that takes both variables as first arguments? The dispatch table is explicitly recreating the pass-arguments-to-subroutine functionality of the language.

    If the main reason you're calling subs based on variables is just to refactor code, there's got to be a better way.

    If you have time, please consider an alternative implementation. Just my 2 cents.
Re: Calling subroutines based on variable names...
by planetscape (Chancellor) on Apr 06, 2008 at 05:27 UTC