Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

execute a string as a function

by fionbarr (Pilgrim)
on Aug 06, 2013 at 15:25 UTC ( #1048134=perlquestion: print w/ replies, xml ) Need Help??
fionbarr has asked for the wisdom of the Perl Monks concerning the following question:

I have this code:
&unpack_a( $lines[$_] ) if ( $RECORD_SEQ_ID eq 'A' ); &unpack_b( $lines[$_] ) if ( $RECORD_SEQ_ID eq 'B' ); &unpack_c( $lines[$_] ) if ( $RECORD_SEQ_ID eq 'C' );
I would like to do something like this:
my $fun = "&UNPACK_$RECORD_SEQ_ID('$lines[$_]')";
and execute this this possible?

Comment on execute a string as a function
Select or Download Code
Re: execute a string as a function
by Corion (Pope) on Aug 06, 2013 at 15:30 UTC

    While what you describe is possible in principle through Perl built-ins, it's usually best to use the technique of a dispatch table:

    my %record_seq_handler= ( 'A' => \&unpack_a, 'B' => \&unpack_B, 'C' => \&unpack_C, ); my $handler= $record_seq_handler{ $RECORD_SEQ_ID } or die "Unknown record sequence '$RECORD_SEQ_ID'"; $handler->( $lines[$_] );

    The way you described directly would be through eval, but this approach has various pitfalls that the above code avoids.

Re: execute a string as a function
by choroba (Abbot) on Aug 06, 2013 at 15:31 UTC
    Use a dispatch table:
    my %dispatch = ( A => \&unpack_a, B => \&unpack_b, C => \&unpack_c, ); # ... $dispatch{$RECORD_SEQ_ID}->($lines[$_]);
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      thanks to both!
Re: execute a string as a function
by CountZero (Bishop) on Aug 06, 2013 at 16:21 UTC
    And don't call your subroutines with the '&' added to its name. It has certain side-effects you do not need.


    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
      I'll bite.

      What side-effects?

          &NAME(LIST);   # Circumvent prototypes.
          &NAME;         # Makes current @_ visible to called subroutine.
Re: execute a string as a function
by sundialsvc4 (Abbot) on Aug 06, 2013 at 17:29 UTC

    Definitely dispatch .. avoids the Bobby Tables Problem, which has many manifestations.   You should also preface this with an explicit test to verify that a key does exist in the dispatch table, e.g.:

    die "No key for '$foo!'" unless exists($dispatch->{$foo});
    ... making sure, of course, that this message (specifically, $foo), in un-sanitized form cannot by any means make its way into any user-delivered output, where it could conceivably be a vector for script-injection.   The message should appear only in unpublished log-files (STDERR).

    As just one of its many advantages, this technique avoids the overhead of “compiling at runtime,” and it expressly indicates the full extent of what you, the designer, intended for the software to do in every case, “and here are all the cases.”   With a mere glance at the source code, anyone can plainly see what the software is to do given any possible input, malicious or otherwise, and can be certain that this is what will occur.

      This script is dealing with (if I'm guessing correctly) processing of biological sequences. It's doubtful that script injection would be a concern here...


        We could be looking at the first chemical to electronic host-jumping virus! Best to be safe.

Re: execute a string as a function
by LanX (Canon) on Oct 06, 2013 at 14:03 UTC
    strange, nobody mentioned using OOP yet

    DB<147> ;{ package tst; sub a { "A" }; sub b {"B"} } DB<148> map { tst->$_ } 'a','b','a' => ("A", "B", "A")

    classes and objects are essentially dispatch tables and methods are strings!

    ( just be careful about $_[0] :)

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re: execute a string as a function
by mtve (Chaplain) on Oct 09, 2013 at 07:49 UTC

    dispatchers are good, but with DRY principle you may use code like this

    use warnings; use strict; sub unpack_a { print "a(@_)\n"; 11 } sub unpack_b { print "b(@_)\n"; 22 } my $RECORD_SEQ_ID = 'a'; local $_ = 0; my @lines = 42; my $res = do { no strict 'refs'; &{"unpack_$RECORD_SEQ_ID"} ($lines[$_ +]) }; print $res;

    Yes, it's not so secure if you don't understand what you're doing, and it's around 20% slower then dispatchers which is usually does not matter.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1048134]
Approved by Corion
Front-paged by Arunbear
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (6)
As of 2014-09-23 07:14 GMT
Find Nodes?
    Voting Booth?

    How do you remember the number of days in each month?

    Results (210 votes), past polls