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

Let's say I have the following code:
use strict; use warnings; package Blah; sub new { bless {}, shift } sub Foo { print "Foo\n"; } sub Bar { print "Bar\n"; } package main; my %Movement = ( foo => 'Foo', bar => 'Bar', ); my $foo = Blah->new; foreach my $key (keys %Movement) { my $func = $Movement{$key}; $foo->$func; }
What I want to do is instead of the two lines in the foreach loop, I want one line. Something like:
foreach my $key (keys %Movement) { $foo->$Movement{$key}; }
But, that doesn't work. (Otherwise, I wouldn't be posting!) Any thoughts?

------
We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Replies are listed 'Best First'.
Re: Weird function calling...
by robin (Chaplain) on Jan 07, 2002 at 23:25 UTC
    If you rewrite the loop as:
    while (my ($key, $func) = each %Movement) { $foo->$func; }
    then you avoid the problem altogether, and you also avoid having to drop the whole key list onto the stack and dereference the hash needlessly.

    I think each is underused, and is a better idiom for many loops which use keys.

        I must admit I'd assumed that dragonchild was using the key, but had omitted it from the example code for the sake of simplicity. Why use a hash at all, otherwise? But I shouldn't make assumptions without mentioning them.

        Your code is very neat and concise, but if the hash is large, it may be impractical to dump all the values onto the stack. each really has much nicer semantics, even if it's slightly more cluttered syntactically. Of course, when we get lazy lists in Perl 6 we might be able to have both at once :-)

Re: Weird function calling...
by runrig (Abbot) on Jan 07, 2002 at 23:17 UTC
    I'm not sure I like this any better (only because it makes you name $foo twice), but it works:
    foreach my $key (keys %Movement) { $foo->can($Movement{$key})->($foo); } # Update: this works too: $foo->${\$Movement{$key}};
    Or you can iterate through the values of Movement, or use each if you need both keys and values (neither of which work if you want to sort the keys)...
Re: Weird function calling...
by Netmonger (Initiate) on Jan 09, 2002 at 00:57 UTC
    What about:
    foreach my $key (keys %Movement) {
        &foo->$Movement{$key};
    }
    
      Well, that doesn't work. You've got your syntax and data types all mixed up. 'foo' is not a subroutine, its a blessed object (and a scalar), and $Movement{key} is a method name (just a scalar and a string). If $foo were a subroutine reference and $Movement{key} were an argument to the subroutine, you could say:
      $foo->($Movement{$key});
      But that's not the case here either.