How to call a subroutine in perl using a variable name

Let's say I have one array containing the entire name of the subroutine, and I want to call everything one by one.

foreach $sub (@arr){ print "Calling $sub\n"; #---How to call $sub?---- &$sub; ## will not work } 
+5
source share
2 answers

In general, your code is correct, but you need to disable strict 'refs' so that Perl allows you to use the contents of the variable as ref code.

 use strict; use warnings; sub foo { print "foo" } sub bar { print "bar" } my @arr = qw/foo bar/; foreach my $sub (@arr) { no strict 'refs'; print "Calling $sub\n"; &$sub(); } 

The output is here:

 Calling foo fooCalling bar bar 

I also added a parenthesis () after the call. Therefore, we do not pass the arguments to %$sub . If we do not, the argument list @_ current routine will be used.


However, you probably shouldn't do this. Especially if @arr contains user input, this is a big problem. Your user can enter the code. Consider this:

 my @arr = qw/CORE::die/; 

Now we get the following result:

 Calling CORE::die Died at /home/code/scratch.pl line 1492. 

Unfortunately. You do not want to do this. The die example is not very bad, but you can easily call the code in another package that was not intended.

It is probably best to do a distribution table. There is a whole chapter about those in Perl of a higher order, Mark Jason Dominus, which you can download for free on your website .

This basically means that you put all the sub-sites in the hash as links to the code, and then call them in your loop. This way you can control which ones are allowed.

 use strict; use warnings; sub baz { print "baz" } my %dispatch = ( foo => sub { print "foo" }, bar => sub { print "bar" }, baz => \&baz, ); my @arr = qw/foo bar baz wrong_entry/; foreach my $sub ( @arr ) { die "$sub is not allowed" unless exists $dispatch{$sub}; $dispatch{$sub}->(); } 

It is output:

 foobarbaz wrong_entry is not allowed at /home/code/scratch.pl line 1494. 
+10
source

You want to do this using code links.

 foreach my $sub (@arr) { $sub->(); } 

where @arr contains scalars like

 my $rc = sub { print "Anonymous subroutine\n" }; 

or

 sub func { print "Named sub\n" } my $rc = \&func; 

You can manipulate these scalars, like any other, to form an array. However, it is more common and useful to use them as values ​​in a hash, creating a dispatch table.

See perlref and perlsub , and (for example) this post and the links in it for comments and details.

+8
source

Source: https://habr.com/ru/post/1262342/


All Articles