Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I loop through a list of functions in Perl?

I have a list of functions in Perl. Example:

my @funcs = qw (a b c)

Now they all belong to this module Foo::Bar::Stix. I would like to call them iteratively in a loop:

foreach $func (@funcs) {
    Foo::Bar::Stix::$func->(%args)
}

where args is a hash of arguments. However I keep getting this error: "Bad name after :: ..." at the line which contains Foo::Bar::Stix::$func->(%args) How do I fix this error?

a b and c are not function objects but strings

like image 560
biznez Avatar asked Dec 13 '22 03:12

biznez


2 Answers

Rather than storing the names of the functions in your array, store references to them in a hash so that you can refer to them by name. Here's a simple code example:

#!/usr/bin/perl

use strict;
use warnings;

my %func_refs = (
    'a' => \&Foo::Bar::Stix::a,
    'b' => \&Foo::Bar::Stix::b,
    'c' => \&Foo::Bar::Stix::c
);

foreach my $func_ref ( values %func_refs ) {
    print $func_ref->( "woohoo: " ), "\n";
}

{
  package Foo::Bar::Stix;

  sub a {
    my $arg = shift;
    return $arg . "a";
  }

  sub b {
    my $arg = shift;
    return $arg . "b";
  }

  sub c {
    my $arg = shift;
    return $arg . "c";
  }
}

If you're stuck with storing the names for some reason, try this:

my $package    = "Foo::Bar::Stix";
my @func_names = qw/ a b c /;
foreach my $func_name (@func_names) {
    my $str = &{ "$package\::$func_name" }( "woohoo: " );
    print $str, "\n";
}

However, this doesn't work under use strict, and because of this I prefer the first solution. Whatever you do, try to avoid using eval. It's unnecessary, and will likely only cause you problems.

Also, most people who work with Perl capitalize it as Perl rather than PERL. Here's a Stackoverflow question on the subject:

How should I capitalize Perl?

like image 95
James Thompson Avatar answered Jan 08 '23 08:01

James Thompson


Bad answer: use a symbolic reference:

for $func (@funcs) {
    &{"Foo::Bar::Stix::$func"}(\%args);
}

Good answer: use a dispatch table:

my %call_func = (
    'a' => \&Foo::Bar::Stix::a,
    'b' => \&Foo::Bar::Stix::b,
    'c' => \&Foo::Bar::Stix::c,
);
...
for $func (@funcs) {
    $call_func{$func}->(\%args);
}
like image 40
ysth Avatar answered Jan 08 '23 08:01

ysth