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

I can assign scalars through with names kept in variables:

my $foo = "bar"; #Scalar 'foo' set to "bar"
my $$foo = "blah"; #Scalar 'bar' set to "blah"

What I want to do now is call a subroutine of the same name stored in a scalar. If $recordID is "MED", I want to call &MED($recordFH). Saying &$recordID attempts to dereference the scalar. But it isn't holding a reference.

I can do this with switching (or nested if's), but I'm sure there is a more straightforward (magical) way.

Thanks,
Travis

Replies are listed 'Best First'.
Re: Variable Sub Calls
by chromatic (Archbishop) on Mar 16, 2000 at 02:44 UTC
    I just tried this from the command line:
    my $name = "do"; sub do { print "I am doing it\n"; } &$name;
    It printed "I am doing it". There is more than one way to do it:
    my $name = "do"; sub do { print "I am doing this now\n"; } $name->();
    Notice that since both methods use symbolic references, they fail under use strict;. Another approach is:
    $name = \& {"main::$name"}; &$name;
    That depends on being in the main package, however. It does work under use strict.

    A better approach might be building a hash of references to subroutines:

    sub foo { print "Doing foo (whatever that means)\n"; } sub bar { print "Now doing bar (isn't this fun?)\n"; } my %sub_table = ( 'foo' => \&foo, 'bar' => \&bar, ); foreach ( qw (foo bar foobar ) ) { $sub_table{$_}->(); }
    Nicer, isn't it?
Re: Variable Sub Calls
by Anonymous Monk on Mar 16, 2000 at 10:30 UTC
    check the multi-screen CGI example in the perl cookbook... ;-)
RE: Variable Sub Calls
by Anonymous Monk on Mar 16, 2000 at 23:36 UTC
    Check out CGI.pm for real-world examples. It is chock full of exacly what you are trying to do.
A note on style
by Anonymous Monk on Mar 17, 2000 at 06:52 UTC
    On switching, there's a very stylish way to do it in Perl, with which many people aren't familiar. The two are synonyms:
    if ($foo =~ /p1/) { do1; } elsif ($foo =~ /p2/) { do2; } elsif ($foo =~ /p3/) { do3; } else { do4; } SWITCH: for ($foo) { /p1/ && do1 && last; /p2/ && do2 && last; /p3/ && do3 && last; do4; }