Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

strange code (de)referencing behavior

by dsb (Chaplain)
on Feb 10, 2012 at 15:23 UTC ( #953043=perlquestion: print w/replies, xml ) Need Help??
dsb has asked for the wisdom of the Perl Monks concerning the following question:

Hello all,
I've got some behavior I think is a bit odd, and I'm guessing it's just b/c of the way perl handles things internally, but I'm curious as to how/why this is happening.

I have a function being called by a code ref stored in a hash of code refs. The function is passed on the command line, and then by a series of conditions, is called from a class method of package like so:

sub dispatch { my ($self, $fname) = @_; &{$dispatchTable{$fname}}; ## note, no arguments }
Where $fname is the name of a function parse() in a seperate package,

In, parse()'s first few lines are

sub parseAutorep { my $isCombined = shift;
$isCombined is a variable meant to give the user the option to string a series of functions together into a collective check rather than run each individually. In this case, with parse() seeming called with no arguments, I expected $isCombined to be undefined.

However, it's getting set with the object that contains the dispatch() method that is calling parse().

it almost seems like, behind the scenes, the full call looks like:

or something like that.

UPDATE: It actually looks like parse() is getting the same argument list that was passed to the function that called it, dispatch(), if that sheds any light for anyone.

Anyone have any insight? At this point, the simple answer is to just shift the object out of the biggie. But I'm really just curious about what's happening here.

This @ISA my( $cool ) %SIG

Replies are listed 'Best First'.
Re: strange code (de)referencing behavior
by choroba (Chancellor) on Feb 10, 2012 at 15:37 UTC
    Calling a subroutine this way
    forwards the @_ arguments. (Try sub f { say while $_ = shift; warn "Called\n" } %d = (1 => \&f); sub g { &{$d{1}} }; g(1, 2).) If you want to avoid that, use -> for dereference:

      Although I do prefer the arrow notation, the minimal change solution is actually

Re: strange code (de)referencing behavior
by kennethk (Abbot) on Feb 10, 2012 at 15:54 UTC
    If you modify your code to output the content of the incoming argument array,
    sub parseAutorep { print join "\n", map defined ? "'$_'" : '<undef>', @_; }

    your output will be

    'Util' 'parse'
    This is because (as documented in perlsub):
    If a subroutine is called using the & form, the argument list is optional, and if omitted, no @_ array is set up for the subroutine: the @_ array at the time of the call is visible to subroutine instead. This is an efficiency mechanism that new users may wish to avoid.
    The solution is to include parentheses in your call if you really want a null argument list. Alternatively, if you'd like the option of passing additional arguments, you could just shift both the package and subroutine name off the argument stack:
    sub dispatch { my ($self, $fname) = (shift,shift); &{$dispatchTable{$fname}}; }
Re: strange code (de)referencing behavior
by Anonymous Monk on Feb 10, 2012 at 15:52 UTC
    $ perl -le " $f = sub { warn @_; }; sub f { &{$f}; } f(6,6,6); " 666 at -e line 1. $ perl -le " $f = sub { warn @_; }; sub f { $f->(); } f(6,6,6); " Warning: something's wrong at -e line 1.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://953043]
Approved by herveus
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (9)
As of 2017-03-25 15:59 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (311 votes). Check out past polls.