views:

215

answers:

5

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

+1  A: 

Slight change of syntax will give you what you want

Foo::Bar::Stix->$func(%args)

Though this will pass the package name as the first parameter.

Beano
+3  A: 

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);
}
ysth
I totally agree with you, I said the same in my answer.
James Thompson
+9  A: 

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?

James Thompson
+1 for linking to the capitalization question. Your karma will be so bad that nothing will work if you think of Perl as PERL.
innaM
`$Foo::Bar::Stix::{$func}->(%args);` would also work, and doesn't require turning off strict.
Brad Gilbert
A: 
Brad Gilbert
+1  A: 

You can use can

my @funcs = qw (a b c)
foreach $func (@funcs) {
    Foo::Bar::Stix->can($func)->(%args)
}
Hynek -Pichi- Vychodil
I prefer to use `qw' a b c'` or `qw" a b c "` on Stack Overflow, so that the highlighting is more reasonable.
Brad Gilbert