Uri Guttman said:
the guidelines don't contain comments on perl coding. but the regulars
have always encouraged dispatch tables over symrefs/eval. this is
definitely material for an FAQ (or several). what is the actual question
being asked here, that symrefs/eval provide a solution?.
how about:
how do i call a sub when i have its name?
and
how do i get an array or hash when i have its name?
those capture the essence of newbies wanting symrefs/eval. both can be
answered with hashes.
Ok, how about a rough draft that can be criticized/expanded/revised? The
following is not a definitive answer: someone with more knowledge,
experience, and writing ability could doubtless do better, but at least
it's a start. If nothing else, maybe it will encourage someone else to
write something better from scratch.
How do I call a subroutine or get the value of a variable when I have the
name of the subroutine or variable?
Use a dispatch table. A dispatch table is implemented with a hash, which
allows you to associate a string value with a reference. (see L<perlref>)
Since references can refer to (nearly) anything, this permits great
flexibility.
For example, here is a dispatch table using subroutine references:
my %dispatch = (
update => \&update,
add => \&add,
error => sub { die "Error: @_" }
default => \&do_something,
);
If we have a desired name in the scalar C<$input>, the associated
subroutine can be called using C<$dispatch{$input}->()>. The subroutines
do not have to be written by you; you can import functions from a module
and use them in your dispatch table.
The code should always handle the case where the input value is not a key
of C<%dispatch>, so we might implement the call like this:
if ( exists $dispatch{$input} ) {
$dispatch{$input}->(@arguments);
}
else {
$dispatch{'default'}->();
# or perhaps an error message... TMTOWTDI
}
or perhaps like this:
my $routine = $dispatch{$input} || die "Cannot find code for $input";
$routine->(@arguments);
The hash entries can be references to any data structure. Here is an
example using arrays:
my %dispatch = (
default => \@default,
1 => \@data1,
2 => \@data2,
other => \@other
);
Now if we want to print the values in @data1 with commas between the
elements, we could say
print join ',', @{$dispatch{1}};
[Maybe a note here about common practical uses of dispatch tables? Or
should that be at the beginning?]