http://www.perlmonks.org?node_id=1039121

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

Here's a minimal test case that reliably reproduces a problem I've been having. As I understand perl, the three sets of print statements ought to produce the same output each time.

use strict; no warnings "numeric"; print "Reusing one variable:\n"; my $val = "ff"; print "(" . ($val & "") . ")\n"; $val = 7; print "(" . ($val & "") . ")\n"; $val = "ff"; print "(" . ($val & "") . ")\n"; print "\n"; print "Using multiple variables:\n"; my $v1 = "ff"; print "(" . ($v1 & "") . ")\n"; my $v2 = 7; print "(" . ($v2 & "") . ")\n"; my $v3 = "ff"; print "(" . ($v3 & "") . ")\n"; print "\n"; print "Using a sub:\n"; sub xx { my $arg = shift; print "(" . ($arg & "") . ")\n"; } xx("ff"); xx(7); xx("ff");

Since xx has no side-effects except for output, there should be no state maintained between multiple calls to it.

However, what this code actually does seems to be depend on what version I'm running it under:

The output of the last set of prints no longer matches the previous two sets, which suggests that there's some state being preserved between calls to the sub. It looks a bit like $arg's numeric status is somehow getting "stuck".

Putting a print inside the subroutine that prints $arg verifies that $arg is receiving the right value. Putting intermediate calls to other subroutines, or other code, in between the calls to xx doesn't seem to change anything, either.

I've trudged my way through the perldeltas between 5.12 and 5.14 and I couldn't see anything relevant, but then I don't really know what it'd come under, and I don't know much about the innards of perl, so it's possible I've completely missed something.

Can anyone shed some light on why this is happening?

Thanks!

  • Comment on Mystery state (possibly about whether an argument is numeric?) being maintained across calls to a sub
  • Select or Download Code

Replies are listed 'Best First'.
Re: Mystery state (possibly about whether an argument is numeric?) being maintained across calls to a sub
by BrowserUk (Patriarch) on Jun 15, 2013 at 14:35 UTC
    Can anyone shed some light on why this is happening?

    Yes. You :) Use Devel::Peek on $arg in the subroutine before and after you assign to it. Eg:

    sub xx { my $arg; Dump( $arg ); $arg = shift; Dump( $arg ); print "(" . ($arg & "") . ")\n"; }

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Thankyou! Apparently I have managed to miss this tool entirely in my perl-ing to date.
Re: Mystery state (possibly about whether an argument is numeric?) being maintained across calls to a sub
by poj (Abbot) on Jun 15, 2013 at 15:21 UTC
      Seems no, not related to bitwise ops. Actually yes, this example shows that addition is not affected.
      use Devel::Peek; use strict; no warnings "numeric"; sub xx { my $arg=shift; Dump( $arg ); print "ARG+1=".($arg+1)."\n"; } xx("ff"); xx(7); xx("ff"); __END__ SV = PV(0x729b78) at 0x754ae0 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) PV = 0x747d90 "ff"\0 CUR = 2 LEN = 8 ARG+1=1 SV = PVNV(0x72b5f0) at 0x754ae0 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 7 NV = 0 PV = 0x747d90 "ff"\0 CUR = 2 LEN = 8 ARG+1=8 SV = PVNV(0x72b5f0) at 0x754ae0 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) IV = 7 NV = 0 PV = 0x747d90 "ff"\0 CUR = 2 LEN = 8 ARG+1=1

        It's not the operation, it is whether the argument is forced from numeric to string.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        From my slightly cargo-culty perspective on what's going on here, I think that bug looks like it - especially given that non-bitwise ops don't seem to show the weirdness, and since nor does putting the constant string in a variable before doing the &:

        use Devel::Peek; use strict; no warnings "numeric"; sub xx { my $arg = shift; my $const = ""; print "(" . ($arg & $const) . ")\n"; } xx("ff"); xx(7); xx("ff");
        This code gives:
        SV = PV(0x100802558) at 0x1008474e0 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) PV = 0x1002074f0 "ff"\0 CUR = 2 LEN = 8 () SV = PVIV(0x100803c58) at 0x1008474e0 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 7 PV = 0x1002074f0 "ff"\0 CUR = 2 LEN = 8 (0) SV = PVIV(0x100803c58) at 0x1008474e0 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) IV = 7 PV = 0x1002074f0 "ff"\0 CUR = 2 LEN = 8 ()