Re: execute a string as a function
by Corion (Patriarch) 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. | [reply] [d/l] |
Re: execute a string as a function
by choroba (Cardinal) on Aug 06, 2013 at 15:31 UTC
|
my %dispatch = (
A => \&unpack_a,
B => \&unpack_b,
C => \&unpack_c,
);
# ...
$dispatch{$RECORD_SEQ_ID}->($lines[$_]);
| [reply] [d/l] |
|
|
| [reply] |
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.
CountZero 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
| [reply] [d/l] |
|
|
I'll bite.
What side-effects?
| [reply] |
|
|
&NAME(LIST); # Circumvent prototypes.
&NAME; # Makes current @_ visible to called subroutine.
| [reply] |
|
|
|
|
|
Re: execute a string as a function
by locked_user 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...
| [reply] |
|
|
| [reply] |
Re: execute a string as a function
by LanX (Saint) 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)
| [reply] [d/l] |
Re: execute a string as a function
by locked_user mtve (Deacon) 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. | |