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

In the following code, the name of the method to be called is calculated at run time:

my $object=MyObj->new(); .... my $method=method_name(...); $object->$method();
This works. Is it possible to do the same without using an auxiliary variable, $method?

-- 
Ronald Fischer <ynnor@mm.st>

Replies are listed 'Best First'.
Re: Syntax question: Method call, where method name is calculated from an expression
by shmem (Chancellor) on Dec 04, 2009 at 14:08 UTC

    Yes, using the reference/dereference trick:

    $object->${\method()}(@args);

    Here, method() is called, a reference to the result is taken through the backslash, and that reference is de-referenced via ${ }. The resulting method is called on behalf of $object, passing along @args.

      Thank you! This works!

      -- 
      Ronald Fischer <ynnor@mm.st>
Re: Syntax question: Method call, where method name is calculated from an expression
by moritz (Cardinal) on Dec 04, 2009 at 12:30 UTC
    use strict; use warnings; use 5.010; sub f { 'g' } sub g { say 'in g()' }; (bless {})->can(f())->();

      Looks great, but this doesn't work if the method expects parameters. For instance:

      package Obj; sub new { my $class=shift; my $self={ x => 'uh' }; bless $self, $class; } sub howl { my ($self,$arg)=@_; print($self->{x}," $arg\n"); } package main; sub mname { 'howl' } my $x=Obj->new(); $x->howl('oh'); $x->can(mname)->('ah');
      The reason is that can() returns only a reference to the method, but the object ($x) is lost on the way. A workaround would be
      $x->can(mname)->($x,'ah');
      but this is ugly, since it requires us to mention the object twice.

      -- 
      Ronald Fischer <ynnor@mm.st>
Re: Syntax question: Method call, where method name is calculated from an expression
by LanX (Saint) on Dec 04, 2009 at 20:47 UTC
    Sorry, this design looks strange, IMHO it breaks OOP paradigms.

    Is there a reason why you don't add the dispatcher as an extra method to the class MyObj?

    $obj->dispatcher(@arguments)

    And even if you need this flexibility and don't care about encapsulation and DRY, you can still define a method call():

    $obj->call(dispatcher(), @arguments)

    giving you more and deeper possibilities to catch possible errors.

    Cheers Rolf

      (Sorry for the late response. I had an accident and was "away from Perl" for nearly 7 weeks)
      Sorry, this design looks strange, IMHO it breaks OOP paradigms.

      It does so on purpose. The code in question has to do with introspection, i.e. method name and arguments come from the outside. See it as kind of a debugging aid.

      Aside from this, I found the question by itself interesting too ;-)
      -- 
      Ronald Fischer <ynnor@mm.st>