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

Folks,

I'd like to be able to call a package method by using variables, one of them being a hash member, like the following. The ProjectA module contains the prepare() function:

use ProjectA; my $project = 'ProjectA'; my %ThingsToDo = (firstTask => 'prepare');

This yields a compilation error:

$project->$ThingsToDo{firstTask}();

Whereas this works allright:

my $temp = $ThingsToDo{firstTask}; $project->$temp();

Is it possible to call the function in the module in this manner without using the $temp variable ?

Thanks.

Replies are listed 'Best First'.
Re: Calling a hash member
by ikegami (Patriarch) on Dec 13, 2006 at 21:08 UTC

    Spliting the statement into two is definitely the way to go.

    my $method = $ThingsToDo{firstTask}; $project->$method();

    The trick used to interpolate function call results into a string also works here, but like in string literals, it's poorly readable.

    $project->${\$ThingsToDo{firstTask}}();
Re: Calling a hash member
by geekphilosopher (Friar) on Dec 13, 2006 at 21:22 UTC

    If you really don't want to use a temporary variable (though I don't see why not), it may be possible to store a hard reference instead of a soft reference:

    use ProjectA; my $project = 'ProjectA'; my %ThingsToDo = (firstTask => \{$project->prepare}); $ThingsToDo{firstTask};

    Alternatively, you could make a dispatcher method in the ProjectA class that executes a given method:

    use ProjectA; my $project = 'ProjectA'; my %ThingsToDo = (firstTask => 'prepare'); $project->doMethod($ThingsToDo{firstTask});
      Your first snippet doesn't work. For example, the following doesn't print 1 and 2.
      { package ProjectA; { my $i; sub prepare { print ++$i, "\n"; } } } my $project = 'ProjectA'; my %ThingsToDo = (firstTask => \{$project->prepare}); $ThingsToDo{firstTask}; $ThingsToDo{firstTask};

        Hrm, good catch. Do you happen to know why this doesn't work? Does the coderef not maintain the closure or something?

      That should probably have been:

      use ProjectA; my $project = 'ProjectA'; my %ThingsToDo = (firstTask => sub { $project->prepare }); $ThingsToDo{firstTask}->();
Re: Calling a hash member
by leocharre (Priest) on Dec 14, 2006 at 04:54 UTC

    I'm not sure if this applies here.. But I got a funny feeling.

    If you are doing object oriented, then..
    #!/usr/bin/perl -w use strict; my $o = new Wonderful; print $o->whichmethod('one'); print $o->whichmethod('two'); exit; package Wonderful; sub new { my $class = shift; my $self= {}; bless $self, $class; return $self; } sub whichmethod { my $self = shift; my $which_method = shift; my $method = { # this will not work!: one => \&method1 one => sub { $self->method1 }, two => sub { $self->method2 }, }; return &{$method->{$which_method}}; } sub method1 { my $self= shift; return 1 } sub method2 { my $self = shift; return 2; } 1;
Re: Calling a hash member
by Devanchya (Beadle) on Dec 13, 2006 at 22:25 UTC
Re: Calling a hash member
by ysth (Canon) on Dec 13, 2006 at 22:17 UTC
    I'd like this to work someday:
    $project->do{$ThingsToDo{firstTask}}();