Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

oo code ref

by Anonymous Monk
on Nov 10, 2008 at 11:38 UTC ( #722627=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

How does one create a code ref to an oo function? i.e. I want to do goto \&{$self->myFunction} or something like that.

Comment on oo code ref
Download Code
Re: oo code ref
by jwkrahn (Monsignor) on Nov 10, 2008 at 11:46 UTC

    You can't goto a reference.   Have you tried goto &{$self->myFunction}?

Re: oo code ref
by JavaFan (Canon) on Nov 10, 2008 at 11:47 UTC
    use strict; use warnings; use 5.010; package Foo; sub x {say "Hello"} package main; foo(); sub foo { my $obj = bless [], 'Foo'; my $sub = $obj->can('x'); goto &$sub } __END__ Hello

      You'll probably want to unshift @_, $obj before goto &$sub to get the invocant into the argument list.

Re: oo code ref
by dragonchild (Archbishop) on Nov 10, 2008 at 14:43 UTC
    my $code_ref = $self->can('myFunction'); unshift @_, $self; # Assuming you don't already have an invocant in @_ goto &$code_ref;

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: oo code ref
by jeffa (Chancellor) on Nov 10, 2008 at 15:40 UTC

    It has been said that Perl is a loaded gun pointed right at your foot. If that is true, then Perlmonks is the shooting range. Ask ... and ye SHALL receive.

    Now, while the good monks have already shown you how to do what you want, someone else really needs to come along and say -- why do need to do that? Don't do that. Wouldn't this work just as well?

    my $result = $self->myFunction();
    Why are you using a goto on a ref to a method when you already have a ref to it via the object itself? Inquired monks want to know. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Why are you using a goto on a ref to a method when you already have a ref to it

      I'm not the OP, so I can only speculate on what the intention might have been...  but maybe the idea was to not mess up the call stack? Compare:

      #!/usr/bin/perl package Foo; use Carp "cluck"; sub new { my $class = shift; return bless { @_ }, $class; } sub myFunction { my $self = shift; cluck $self->{msg}; } sub foo1 { my $self = $_[0]; my $func = $self->can('myFunction'); goto &$func; } sub foo2 { my $self = shift; my $func = sub { $self->myFunction }; goto &$func; } sub foo3 { my $self = shift; $self->myFunction(); } package main; my $obj = Foo->new( msg => "foo" ); $obj->myFunction(); # direct call $obj->foo1(); # indirect, using goto (transparent) $obj->foo2(); # indirect, using goto via closure $obj->foo3(); # indirect, using regular call via $self

      Output:

      foo at ./722627.pl line 16 Foo::myFunction('Foo=HASH(0x63c430)') called at ./722627.pl li +ne 40 foo at ./722627.pl line 16 Foo::myFunction('Foo=HASH(0x63c430)') called at ./722627.pl li +ne 41 foo at ./722627.pl line 16 Foo::myFunction('Foo=HASH(0x63c430)') called at ./722627.pl li +ne 27 Foo::__ANON__() called at ./722627.pl line 42 foo at ./722627.pl line 16 Foo::myFunction('Foo=HASH(0x63c430)') called at ./722627.pl li +ne 33 Foo::foo3('Foo=HASH(0x63c430)') called at ./722627.pl line 43

      Only the goto variant of foo1() is leaving behind a call stack comparable to the direct call.

Re: oo code ref
by jbert (Priest) on Nov 10, 2008 at 15:51 UTC
    If you want a goto because you don't want to continue in your existing function any more, then that means you want a return:
    return $self->myFunction;
    If you really do want a code ref which allows you to make use of $self, then you can create one with sub:
    # Pick a method, wrap it up an a coderef and return it sub method_chooser { my $self = shift; return (rand % 2) : ? sub { $self->runAlice; } : sub { $self->runCha +rlie }; } sub do_stuff { my $self = shift; # Dunno what the chooser will choose my $code_ref = $self->method_chooser(); # But run it all the same $code_ref->(); }
    Note that method_chooser will return a coderef which stores ('closes over') the value of $self. i.e. it will keep a reference to your object. This is handy, but it obviously counts as a reference for reference counting purposes, i.e. you can get a ref loop that way (and the consequent memory leak).
Re: oo code ref
by stvn (Monsignor) on Nov 11, 2008 at 02:37 UTC

    I think perhaps this is what you are a looking for:

    my $meth = 'myFunction'; $obj->$meth(@args);
    You can also do this:
    my $meth = $obj->can('myFunction'); $obj->$meth(@args);
    In general I would avoid goto since it is hard to get the dispatching right and you have to fiddle with @_ all of which will make your code that much harder to understand.

    If you actually want a code reference to the method so that you can call it later on and have everything Just Work, then you want to use a closure like this:

    my $meth = sub { $obj->myFunction(@_) };
    Then later on you can just do:
    $meth->(@args);
    And you dont have to worry about making sure $self is properly on @_ etc etc.

    -stvn

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://722627]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2014-09-21 22:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (176 votes), past polls