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

Does anybody know if there is a way to call a Perl sub routine which is stored in a scaler variable? For Instance:
$var = "func1"; #call $var; sub func1 { print "here"; }

Replies are listed 'Best First'.
Re: Calling a subroutine from a scalar
by dragonchild (Archbishop) on Jun 29, 2005 at 15:08 UTC
    There's plenty of ways. The best is this:
    use strict; sub func1 { print "Here\n"; } my $var = \&func1; $var->();
    You take a reference to the function and store it in a scalar, then dereference the scalar.

    If you want to use the name of the function, the best thing to do is a dispatch table.

    my %dispatch = ( func1 => \&func1, func2 => \&func2, ); my $var = 'func1'; $dispatch{$var}->();

    This way, you know which function names will be used and how they will be used.


    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 a subroutine from a scalar
by friedo (Prior) on Jun 29, 2005 at 15:07 UTC
    &{ $var }(@args);

    Personally, I would reccomend storing dynamically named subs in a hash, instead, though.

    my %subs = ( foo => sub { print 42 }, bar => sub { print "abc" } ); $subs{foo}->(@args);
Re: Calling a subroutine from a scalar
by tlm (Prior) on Jun 29, 2005 at 15:47 UTC

    Your question suggests a logical confusion. One can't store a subroutine in a scalar variable. You can store a reference to a subroutine in a scalar variable, or you can, as in your code, store the name of a subroutine in a scalar variable.

    In the former case, the answer to your question is easy:

    my $coderef = \&some_sub; # $coderef contains a reference to &some_su +b my $results = $coderef->();

    In the latter case, you can either use eval:

    my $subname = 'some_sub'; my $results = eval "$subname()"; die $@ if $@;
    or you can treat it as a symbolic ref:
    my $results = do { no strict 'refs'; $subname->() };

    use strict; use warnings; sub some_sub { print "Hello world!\n"; return 42; } my $coderef = \&some_sub; my $subname = 'some_sub'; print $coderef->(), "\n"; print eval "$subname()", "\n"; die $@ if $@; print do { no strict 'refs'; $subname->() }, "\n"; __END__ Hello world! 42 Hello world! 42 Hello world! 42

    But storing names of subroutines in variables should be a red flag to alert you that you are probably not thinking about the problem in the right way.

    the lowliest monk

Re: Calling a subroutine from a scalar
by blazar (Canon) on Jun 29, 2005 at 15:06 UTC
    Don't! perlref instead. Then ->.

    Update: I feel reluctant to add this, but what you asked for is really possible through an exotic beast you should ignore for the moment, called symref. But as I wrote above, Don't. If you explain in more detail what it is that you really want, then someone will certainly explain you how to achieve it with real refs. My suspect here is that you want a dispatch table...

    Update: I know it is pointless, but would any of those who downvoted this care to explain why?!? Or do you really think we should second a newbie's intuitive desire to use symrefs and teach him/her how to do so?

    Update to the update: as correctly pointed out by davorg at Re^2: Calling a subroutine from a scalar, I originally had mistyped perlre for perlref

      Well, I left you neutral, but I suspect it's because one can use eval, and that doing what the poster is asking needn't be "deep magic" or responded to with what was essentially "you don't want to do that" without even a brief explanation of why.

      For the record, eval could be used thus:

      my $f = 'subroutine'; eval "$f"; sub subroutine { print "In sub!\n"; }
      You are right to say that there are many, many reasons why one doesn't want to use eval this way[0], and that there is probably a better solution. However, I would say that the OP simply didn't provide enough information about what (s)he is trying to accomplish for us to provide useful advice on what approach could prove safer and more efficient.

      [0]: A few reasons, from the top of my head:

      1. Not strict-safe: the name of the func is a bareword string when eval'd
      2. Evaling a string without knowing what is in it is a security risk -- and if you know what's in it, a dispatch table or some similar structure is probably a better choice anyhow
      3. Evaling a string is slow (evaling a block isn't, compartively)

      Yoda would agree with Perl design: there is no try{}

      would any of those who downvoted this care to explain why?

      Perhaps it's the link to "perlre" which would seem to be completely useless for this task. Maybe you meant "perlref" instead.

      --
      <http://www.dave.org.uk>

      "The first rule of Perl club is you do not talk about Perl club."
      -- Chip Salzenberg

        D'Oh! Yet Another Typo(TM)... I'm updating it soon.
      I have not down-voted your node but I do think the knee-jerk anti-symref response in the case of symbolic CODE references is often inappropriate.

      It is perfectly reasonable to use a Perl package as a dispatch table. After all that's excatly what Perl's object implementation does.

      Do you think...

      FOO->$bar();
      ...is really any better than...
      no strict 'refs'; "FOO::$bar"->();
      ... when you are not thinking in a OO way?

      It should be noted that the security concern often leveled at symbolic CODE refs (that a malicious user could use a qualified name to access a subroutine outside the dispatch table) actually applies in the indirect class method call but does not apply in the explicit symref case.

        I take your point wrt CODE symrefs, and in fact I upvoted your post. OTOH in my experience I fully agree with the widespread consensus that symrefs in general are bad. Not to say that I do not use them myself when I do want to manipulate the symbol table, but that's a whole different story. In most standard situations in which newbies would (naively) like to use symrefs, real refs would only require a moderate amount of more typing, and if you're under strict, actually less, for you have to say no strict 'refs' then. So, all in all, they should be advised against doing so until they are knowledgeable enough to know when it would be the case.