Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

calling subs using references.

by opensourcer (Monk)
on May 22, 2007 at 10:08 UTC ( [id://616716]=perlquestion: print w/replies, xml ) Need Help??

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

i'm trying to call a subroutine using references. Some how im making a mistake, but don't know where.
package Test; use strict; sub new { my ($caller, @args) = @_; return bless {}, $caller || ref($caller); } sub test1 { print "Worked from 1\n"; } sub test2 { print "Worked from 2\n"; } package main; use Test; my $tes = new Test; my $rf = { test1 => 'test1', test2 => 'test2', }; no strict 'refs'; no strict 'subs'; $tes->$rf->{test1}();

Replies are listed 'Best First'.
Re: calling subs using references.
by johngg (Canon) on May 22, 2007 at 10:27 UTC
    At a quick glance you need to change the placement of parentheses in your last line.

    $tes->($rf->{test1});

    Cheers,

    JohnGG

Re: calling subs using references.
by jettero (Monsignor) on May 22, 2007 at 10:37 UTC

    Personally, I might even store a ref in the $rf rather than using no strict refs.

    my $rf = { test1 => \&Test::test1 }; $rf->{test1}->($tes); # tada!!

    I then passed the object to the thing so it'd work like the method call. I might even argue that the callback table should be a member of the Test package itself. Kinda depends on your setup, but when you find yourself using no strict 'refs' you're probably (though, not always) overthinking the problem.

    I'm not sure you need the no strict 'refs' at all here though. My tests seem to indicate that $x->$y() is fine without that pragma.

    UPDATE: blazar++

    -Paul

Re: calling subs using references.
by shmem (Chancellor) on May 22, 2007 at 10:39 UTC
    Since the dereferencing chain is ambiguous, you have to resolve it yourself:
    my $word = $rf->{test1}; $tes->$word();

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      Since the dereferencing chain is ambiguous, you have to resolve it yourself:

      my $word = $rf->{test1}; $tes->$word();

      Well, I asked something very similar some time ago. A particularly interesting reply deals both with symbolic and real references: AIUI

      $tes->${\$rf->{test1}}();

      should work. I haven't tested it though, so caveat. Even if it works, it's certainly clumsy and not very friendly to people seeing it.

Re: calling subs using references.
by rhesa (Vicar) on May 22, 2007 at 10:34 UTC
    If your goal is to call $tes->test1(), then try this:
    my $method = $rf->{test1}; $tes->$method();
Re: calling subs using references.
by rinceWind (Monsignor) on May 22, 2007 at 14:46 UTC

    I have a niggle. There's a misquoted idiom in your constructor. The line is:

    return bless {}, $caller || ref($caller);

    If $caller is false, there's no way it can be a reference. The idiom you've misquoted has the or round the other way, which allows the user to pass in an existing object from which you derive the package name.

    In practice, nobody's ever going to call new on an existing object. There's thus no need to document and test for this special case, just code it as:

    return bless {}, $caller;

    --
    wetware hacker
    (Qualified NLP Practitioner and Hypnotherapist)

Re: calling subs using references.
by naikonta (Curate) on May 22, 2007 at 13:43 UTC
    I think the replies have spotted the problem and given solution as well. I just want to let you know that you have a serious bug in your constructor so it can't be called by objects. You need to swap the || operands.
    my $t = Test->new; my $t1 = $t->new; # Attempt to bless into a reference
    I'm aware that this is an example code, and I hope this is not what you have in your real code.

    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (5)
As of 2024-03-28 17:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found