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

If you have this perl code:

package Foo; use strict; sub new { return bless {f => 'foo'}, $_[0]; } sub foo { shift; print "@_\n"; } 1; package main; use strict; my $a = new Foo(); my $f = $a->{f}; no strict qw(subs); $a->$f('foobar'); 1; __END__

I would like invoke 'foo' method in a more compress form, such as:

$a->${$a->{f}}('foobar');

but this latter form doesn't work!!

Any idea???

Replies are listed 'Best First'.
Re: Invoke object methods with a symbolic reference
by mirod (Canon) on Feb 14, 2001 at 18:13 UTC

    I don't quite get the compactness of $a->${$a->{f}}('foobar'); but maybe what you are loking for is to store a reference to the foo method instead of its name:

    sub new { return bless {f => \&foo}, $_[0]; } # \&foo is a reference to foo()

    And then you can call the subroutine (including under use strict) as $a->{f}('foobar'); just note that in this case foo is just a regular function, not a method any more and you either have to remove the shift in the function or pass it $a.

      You could do the same by generating a closure to pass it $a == $self:

      sub new { my $self = {}; bless $self, $_[0]; $self->{f} = sub { &foo ($self, @_); }; return $self; }

      The only reason for the three-line form with temporary variable is that I can't figure out how else to embed the closure "reference" to the object ($self) inside of an hash inside of the object itself :-)

      (fixed minor typo!)

Re: Invoke object methods with a symbolic reference
by merlyn (Sage) on Feb 14, 2001 at 19:51 UTC
    It doesn't work because the symbolic invocation format isn't fully orthogonal. You could do something like this instead:
    $a->can($a->{f})($a, 'foobar');
    But I don't know if that's any better than what you have. By the way, you don't need no strict subs, since this isn't considered a symbolic reference. In fact, no strict subs deals with barewords: not even related here!

    -- Randal L. Schwartz, Perl hacker