Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I elegantly call a Perl subroutine whose name is held in a variable?

Tags:

perl

I keep the name of the subroutine I want to call at runtime in a variable called $action. Then I use this to call that sub at the right time:

&{\&{$action}}(); 

Works fine. The only thing I don't like is that it's ugly and every time I do it, I feel beholden to add a comment for the next developer:

# call the sub by the name of $action 

Anyone know a prettier way of doing this?


UPDATE: The idea here was to avoid having to maintain a dispatch table every time I added a new callable sub, since I am the sole developer, I'm not worried about other programmers following or not following the 'rules'. Sacrificing a bit of security for my convenience. Instead my dispatch module would check $action to make sure that 1) it is the name of a defined subroutine and not malicious code to run with eval, and 2) that it wouldn't run any sub prefaced by an underscore, which would be marked as internal-only subs by this naming convention.

Any thoughts on this approach? Whitelisting subroutines in the dispatch table is something I will forget all the time, and my clients would rather me err on the side of "it works" than "it's wicked secure". (very limited time to develop apps)


FINAL UPDATE: I think I've decided on a dispatch table after all. Although I'd be curious if anyone who reads this question has ever tried to do away with one and how they did it, I have to bow to the collective wisdom here. Thanks to all, many great responses.

like image 995
Marcus Avatar asked Dec 16 '09 16:12

Marcus


People also ask

How do you pass a variable in Perl subroutine?

Passing parameters by references How the program works. First, we defined a subroutine &do_something . Inside the subroutine, we changed the values of the first and second parameters through the argument array @_. Second, we defined two scalar variables $a and $b , and initialized their values to 10 and 20.

What does @_ mean in Perl?

Using the Parameter Array (@_) Perl lets you pass any number of parameters to a function. The function decides which parameters to use and in what order.


1 Answers

Rather than storing subroutine names in a variable and calling them, a better way to do this is to use a hash of subroutine references (otherwise known as a dispatch table.)

my %actions = ( foo => \&foo,                 bar => \&bar,                 baz => sub { print 'baz!' }                  ...                ); 

Then you can call the right one easily:

$actions{$action}->(); 

You can also add some checking to make sure $action is a valid key in the hash, and so forth.

In general, you should avoid symbolic references (what you're doing now) as they cause all kinds of problems. In addition, using real subroutine references will work with strict turned on.

like image 159
friedo Avatar answered Sep 29 '22 17:09

friedo