Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

calling subs using references.

by opensourcer (Monk)
on May 22, 2007 at 10:08 UTC ( #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 (Abbot) on May 22, 2007 at 10:27 UTC
    At a quick glance you need to change the placement of parentheses in your last line.




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++


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();


    _($_=" "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


      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?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://616716]
Approved by jettero
[stevieb]: well, what happens is the Arduino 'listens' for requests r/w, and does the appropriate thing when it's interrupted based on the 'register' address sent in. It's ugly as it was my first attempt, but I've got great new ideas I'm just sitting.
[stevieb]: ...down to implement now. Here's the sketch as it currently sits
[shmem]: well I use I2C and SPI and stuff, but creating a pseudo chip looks to me like lot of indirection and memory clutter... not?
[choroba]: Are you going to use the device soon? Related to your comment about "not having much time to do a lot of coding"...
[stevieb]: sure, but I'm just learning ;) I consider it practice to get a good understanding of what goes on *after* an I2C/SPI request is made
[shmem]: ah ok. Gonna read that. but now....
shmem compiles himself into his template
[stevieb]: this is my RPi:: distribution overall automation build system physical layout. It doesn't encompass all of my RPi dists yet, ...
[stevieb]: ...but I'm getting close. I've been soldering my own PCBs to gain that experience as well, before I have my own manufactured.
[stevieb]: heh, nice *template* ;) 'night shmem!

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (9)
As of 2017-06-25 22:45 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (572 votes). Check out past polls.