Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

How can I call a Perl sub with an object from a sub name stored in a var?

by misterperl (Pilgrim)
on Dec 08, 2020 at 16:16 UTC ( #11124839=perlquestion: print w/replies, xml ) Need Help??

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

Hello respected ones!

I want to call

$self->$mysub ( $myargs)

my usual approach is something like

 &$self->$mysub ( eval $myargs )

which has the undesirable action of adding "main::" in front of $self and of course blowing up the syntax. I also tried "eval" instead of && no joy..

TY and Happy Holidays!

Replies are listed 'Best First'.
Re: How can I call a Perl sub with an object from a sub name stored in a var?
by stevieb (Canon) on Dec 08, 2020 at 16:35 UTC

    Perhaps it would help if you showed the implementation code, instead of just a single line, because it works fine for me:

    package Foo; use warnings; use strict; sub new { return bless {}, $_[0]; } sub blah { my ($self, $args) = @_; my $method = 'process'; my $updated = $self->$method($args); return $updated; } sub process { my ($self, $args) = @_; my @updated; push @updated, $_ * 2 for @$args; return \@updated; } package main; my $obj = Foo->new; my $method = 'blah'; my $args = [qw(1 2 3)]; my $return = $obj->$method($args); print "$_\n" for @$return;

    Output

    spek@scelia ~/scratch $ perl obj.pl 2 4 6

    In my test suites, I very often put package and method names within variables to shorten the amount I have to type, as in each test file, I have a block for each group of tests, and there can be hundreds of tests, so instead of dozens of:

    # test A { my $object = Some::Package::Name->new; is $object->some_method_name($y), 1, "some_method_name() with arg +$y ok"; ... } # test B { my $object = Some::Package::Name->new; is $object->some_method_name($z), 2, "some_method_name() with arg +$z ok"; ... } ...

    I do this:

    ... my $mod = 'Some::Package::Name'; my $m = 'method_tested_in_this_test_file'; # testA { my $o = $mod->new; is $o->$m($arg), 1, "return val of $m with arg $arg ok"; ... } # testB { my $o = $mod->new; is eval {$o->$m('blah'); 1}, undef, "$m croaks if sent in 'blah'"; like $@, qr/idiot!/, "...and error message is sane"; ... } ...

    And so on and so forth.

    Update: Modified example to show method name as string within the object ($self) as well as outside of it.

      Oh my - I guess I way-over-complicated this. All I need is:

      my $return = $obj->$method($args);

      I didn't know the method could be a variable.

      TY Vote ++ for all!

        One thing I forgot to mention is that the variable that encompasses the name of the subroutine should somehow reflect which sub it represents.

        Doing something like the following in a file with hundreds or thousands of lines of code can be frustratingly confusing:

        my $method_1 = 'twist_rubber_arm'; my $var_6 = 'choke_chicken'; my $x = 'let_cat_out_of_bag'; # far, far later on in the code say $object->$var_6('tomorrow');

        What the hell is $var_6 again?!? Time to go wading through code. Even with a good editor/IDE, backtracking is a time sink. Best to use names that are clearly representative in some way (as with all variables regardless if they map to a subroutine or not).

        $object->$method( @args );

        $method can be a string (method name) or a coderef.

        It can also be an overloaded object though, in which case it is stringified, not coderefified.

        Yep, sometimes us programmers tend to think that the easy way must be wrong because it's too easy ;)

Re: How can I call a Perl sub with an object from a sub name stored in a var?
by Corion (Patriarch) on Dec 08, 2020 at 16:37 UTC
    $self->$mysub ( eval $myargs)

    should already work, at least for:

    my $mysub = sub { say "@_" }; my $self = {}; my $myargs = "1,2,3"; $self->$mysub( eval $myargs );
Re: How can I call a Perl sub with an object from a sub name stored in a var?
by LanX (Saint) on Dec 08, 2020 at 16:23 UTC
    > my usual approach is something like

     &$self->$mysub ( eval $myargs )

    WHY? oO

    What is the content of $self?

    That's pretty cryptic code. By convention is $self an object (i.e. a blessed ref) ... not the name of a sub.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      the methods are written, expecting an object.....
        Define yourself a custom function to do your "approach".

        I called it cryptic, guess why...

        DB<170> sub cryptic { my ($func,$meth,$args) = @_ ; $func->()->$meth +(eval $args) } DB<171> x [$self,$mysub,$myargs] 0 ARRAY(0x3c46108) 0 'bla' 1 'test' 2 '$a,$b' DB<172> &$self->$mysub ( eval $myargs ) [bless({}, "TEMP"), 42, 666] DB<173> cryptic( 'bla' , 'test', '$a,$b' ) [bless({}, "TEMP"), 42, 666] DB<174>

        you'll probably need to deactivate strict inside.

        edit

        and caller will tell you the name of the package from where you called cryptic()

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re: How can I call a Perl sub with an object from a sub name stored in a var?
by perlfan (Vicar) on Dec 11, 2020 at 19:20 UTC
    I think this is backwards. If you're thinking of $myargs to literally unpack to conform to caller semantics, then I'd lose that notion. Just unpack the contents of $_[1] as needed in the resolved subroutine that ends up being called.
    use strict; use warnings; package Foo; sub new { my $pkg = shift; my $self = {}; return $self, $pkg; } sub dispatch { my ($self, $mysub, $myargs) = @_; $self->$mysub($myargs); return; } sub mysub1 { my ($self, $args) = @_; foreach my $arg (split /,/, $args) { print qq{$arg\n}; } } package main; my $foo = Foo->new; $foo->dispatch('mysub1', '1,2,3');

    Output

    prompt$ perl test.pl 1 2 3

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11124839]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2023-12-08 06:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?











    Results (35 votes). Check out past polls.

    Notices?