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

Can I do something like this?
my $name = 'test'; update_$name(); $name = 'hello'; update_$name(); sub update_test { print 'test'; } sub update_hello { print 'hello'; }

Replies are listed 'Best First'.
Re: Dynamically Calling a Subroutine
by Tanktalus (Canon) on Jul 13, 2011 at 00:00 UTC
    #!/usr/bin/perl use strict; use warnings; my $name = shift; my $func = "update_$name"; main->$func(); # "main" should be the namespace the functions are in. sub update_test { print "!test\n" } sub update_hello { print "hello!\n" }
    The downside is that the first parameter to the function is its namespace. In the above example, it's "main". Note the output:
    $ perl x.pl test !test $ perl x.pl hello hello! $ perl x.pl heheh Can't locate object method "update_heheh" via package "main" at x.pl l +ine 10.
    The (more) normal way to do this is:
    #!/usr/bin/perl use strict; use warnings; my $name = shift; my %updates = ( test => \&update_test, hello => \&update_hello, ); $updates{$name}->(); sub update_test { print "!test\n" } sub update_hello { print "hello!\n" }
    Either way, you should check if the function exists before trying to run it, e.g., main->can($func) or exists $updates{$name}.
      Wow. I have forgotten this already.
Re: Dynamically Calling a Subroutine
by BrowserUk (Patriarch) on Jul 12, 2011 at 23:19 UTC

    Globbing:

    sub update_test{ print 'hi' };; $n = 'test';; *{'update_' . $n }->();; hi

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Thanks. It works! But I want to understand why it works.

      Can you explain what is happening in this line?
      *{'update_' . $n }->();

      I thought glob is only used for directories.

        See Globject sigils.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        Remember that perl allows you to have the same name for different things: $foo, @foo, %foo, and foo() (the subroutine 'foo') are all stored in different slots of the symbol table entry for the key 'foo': $foo is in SCALAR, @foo in ARRAY, %foo in HASH, and foo() in the CODE slot. We reference all of these things at once via a "glob".

        The string inside the curlies is the key we'll use to access the symbol table.

        The *{...} (the glob reference syntax) is essentially saying "find the symbol table entry that contains references to all the things with this name".

        The ->() following the dereference says "call what the CODE slot references in this entry." It the sub had arguments, you could put them in the parens.

Re: Dynamically Calling a Subroutine
by 7stud (Deacon) on Jul 13, 2011 at 07:17 UTC
    Thanks. It works! But I want to understand why it works. Can you explain what is happening in this line? *{'update_' . $n }->(); download I thought glob is only used for directories.

    The glob() function is used to search for files.

    On the other hand, perl has many different types: scalars, arrays, hashes, etc. And a perl program can happily have variables named $x, @x, and %x, and it will run without error. A typeglob is one of the types in perl. The typeglob *x represents all variables named 'x' in your program, e.g. $x, @x, %x, sub x {}, etc. In order to understand typeglobs, you need to read perlreftut first, so that you know what references are.

    The code fragment:

    *{'update_' . $n }

    resolves to the typeglob: *update_test. The arrow following the brackets:

    *{'update_' . $n }->

    ...dereferences the reference on the left of the arrow. The type of dereference is determined by what's on the right of the arrow:

    *{'update_' . $n }->()

    In this case, the left side of the arrow, i.e. the typeglob, is treated as a reference to a subroutine, and the subroutine is called. Compare to this:

    #####use strict; use warnings; use 5.010; sub greet { my $greeting = shift; say $greeting; } %greet = ( a => 'hello', b => 'goodbye', ); my $code_ref = \&greet; $code_ref->('hello'); my $hash_ref = \%greet; say $hash_ref->{b}; *greet->('goodbye'); say *greet->{a}; --output:-- hello goodbye goodbye hello
Re: Dynamically Calling a Subroutine
by Somni (Friar) on Jul 13, 2011 at 17:49 UTC
    Typically, I'll revert to a dispatch table for this sort of task:
    my %dispatch = ( test => sub { print "test\n" }, hello => sub { print "hello\n" }, ); my $name = 'test'; $dispatch{$name}->(); $name = 'hello'; $dispatch{$name}->();
    This has the benefit of confining your subroutines to a very small namespace, as opposed to the entire symbol table. You can validate your input (lookup the key before calling it), and thereby provide better diagnostics.

    In the event I actually want the symbol table (I can't actually recall wanting this, outside of calling methods...) then I tend to prefer can(). It does have caveats: if you're dealing with a class, it will search up the inheritance tree. However, this is usually something I want.

    my $name = 'test'; __PACKAGE__->can("update_$name")->(); $name = 'hello'; __PACKAGE__->can("update_$name")->(); sub update_test { print "test\n" } sub update_hello { print "hello\n" }
    You can similarly check for the function before simply calling it, by checking the return value of can(), which is a subref.
      I can't find any documentation for the can() function. Link?
Re: Dynamically Calling a Subroutine
by Anonymous Monk on Jul 12, 2011 at 23:42 UTC
    when I added this:
    use strict;
    It gave an error.
    Can't use string ("update_test") as a symbol ref while "strict refs"

      Then use:

      my $result = do{ no strict 'refs'; *{ 'update_' . $n }->() };; hi

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Dynamically Calling a Subroutine
by jim_jr (Initiate) on Mar 13, 2015 at 19:06 UTC
    I just wanted to thank the poser and respondents for this question. It was exactly the information I needed for a project I was working on. I could not find this specific issue on any other support site. Jim in Cleveland