Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Is it possible to use a scalar to call a subroutine?

by bradcathey (Prior)
on May 06, 2010 at 16:45 UTC ( [id://838749]=perlquestion: print w/replies, xml ) Need Help??

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

Fellow Monasterians,

I've searched the "Internets" and the library here in the monastery, but can't find anything definitive. Read lots of stuff about dispatch tables and anonymous subs, and tried several approaches but epic fails. Here's what I'm trying to do. Thoughts? TIA.

my $sub = 'do_this'; print $sub("Fred"); sub do_this { my $var = shift; return "My name is $var"; } sub do_that { my $var = shift; return "My name is not $var"; } My name is Fred

UPDATE: I start getting nervous making exceptions to strict to make things work below, but more importantly, to kennethk's point (below) I might want to rethink why I'm using a variable for a variable name. I had tried to do this many years ago for simple scalars, but got a lesson from one of the senior monks at the time about using hashes, and it changed everything. So, a simple conditional statement or dispatch table might be a better practice.

—Brad
"The important work of moving the world forward does not wait to be done by perfect men." George Eliot

Replies are listed 'Best First'.
Re: Is it possible to use a scalar to call a subroutine?
by kennethk (Abbot) on May 06, 2010 at 16:55 UTC
    You are looking for Symbolic references. The following code does what you intend; However, I would think a dispatch table would be a cleaner, safer and less bug-prone solution to your issue. I, of course, have no idea what that issue is. Please read Why it's stupid to use a variable as a variable name before you use the code.

    #!/usr/bin/perl use strict; use warnings; my $sub = 'do_this'; { no strict "refs"; print $sub->("Fred"); } sub do_this { my $var = shift; return "My name is $var"; } sub do_that { my $var = shift; return "My name is not $var"; } __END__ My name is Fred

    And with a dispatch table, which leaves strict intact:

    #!/usr/bin/perl use strict; use warnings; my %dispatch_table = ( do_this => sub { my $var = shift; return "My name is $var"; }, do_that => sub { my $var = shift; return "My name is not $var"; }, ); my $sub_name = 'do_this'; print $dispatch_table{$sub_name}("Fred"); __END__ My name is Fred
      I don't think I'd like a solution where named subs disappear as anon subs in hashes, using strings to look them up. Yeah, sure, strict is happy, but making strict happy isn't a goal. You've lost some of the benefits strict give you. Using a dispatch table just means you're doing what Perl is doing for you (using stashes) when using symbolic references - with the hash playing the role of a namespace.

      I would use:

      my $sub = \&do_this; print $sub->("Fred");
        Fair criticism, though I would point out the total lack of context on the question at large. How about a compromise, which still lets the user specify their subroutine with a string, as per spec:

        #!/usr/bin/perl use strict; use warnings; my $sub_name = 'do_this'; my %dispatch_table = (do_this => \&do_this, do_that => \&do_that, ); print $dispatch_table{$sub_name}("Fred"); sub do_this { my $var = shift; return "My name is $var"; } sub do_that { my $var = shift; return "My name is not $var"; } __END__ My name is Fred

      Okay, so this falls into the variable-for-a-variable camp. Which is why I stopped trying to this about 6 years ago and started using hashes. Which is basically what a dispatch table is doing.

      It seemed like a good idea at first, but now I'm seeing the logic.

      —Brad
      "The important work of moving the world forward does not wait to be done by perfect men." George Eliot
Re: Is it possible to use a scalar to call a subroutine?
by BrowserUk (Patriarch) on May 06, 2010 at 16:56 UTC

    sub doThis{ print "doThis doing this with $_[0]"; };; { no strict 'refs'; my $sub = 'doThis'; $sub->('fred'); };; doThis doing this with fred
Re: Is it possible to use a scalar to call a subroutine?
by originalgeek (Initiate) on May 06, 2010 at 17:10 UTC
    Try: my $sub = \&do_this;
Re: Is it possible to use a scalar to call a subroutine?
by biohisham (Priest) on May 06, 2010 at 18:23 UTC
    You're almost there, if you turned warnings on you would have seen that the interpreter thought you wanted to print to a filehandle. a tiny modification would've achieved what you're looking for, note the infix arrow operator in the print line..
    use warnings no strict 'refs'; my $sub = 'do_this'; print $sub->("Fred"); sub do_this { my $var = shift; return "My name is $var"; } sub do_that { my $var = shift; return "My name is not $var"; }


    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.
Re: Is it possible to use a scalar to call a subroutine?
by rovf (Priest) on May 07, 2010 at 07:34 UTC

    my $result=eval{$sub); print($@ ? "Exception: $@\n" : $result);

    -- 
    Ronald Fischer <ynnor@mm.st>

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://838749]
Approved by almut
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2024-04-19 10:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found