Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

An obscure side effect?

by BrowserUk (Patriarch)
on Aug 03, 2003 at 02:41 UTC ( [id://280385]=perlquestion: print w/replies, xml ) Need Help??

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

Can anyone explain this? It's got me foxed.

#! perl -slw use strict; sub swab{ substr( $_[0], $_[1], 1 ) ^= substr( $_[0], $_[2], 1 ) ^= substr( $_[0], $_[1], 1 ) ^= substr( $_[0], $_[2], 1 ) } my $t ='AB'; swab( $t, 0, 1 ); print "'$t'"; print "'$t'"; $t ='AB'; swab( $t, 0, 1 ); print "'$t'"; print "'$t'"; __END__ P:\test>swab 'BA' 'BA' ' A' ' A'

And yes. I know and agree there are better ways of coding swab(), but I'm still foxed:)


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.

Replies are listed 'Best First'.
Re: An obscure side effect?
by dws (Chancellor) on Aug 03, 2003 at 03:42 UTC
    Good one. This exhibits the nearly same behavior under 5.8 on Linux. (I get a single character printed the second time around, though the string is still two bytes long.)

    I poked at it a bit to put the parameters into temporaries, but got the same effect. I also tried using a different lexical variable for the second call, but still got the same effect. When I pull the characters out and do the XOR swap on them, I get the right result. That seems to point the finger at substr(). I wonder if some internal optimization has gone awry.

    Time for a bug report.

      On Linux you get a two byte string, where the first character is "\x00", which isn't printable. I expect that on Windows you get the same, but that that character is printed as a space.

      Abigail

      Reported: Ticket #23207.

      Thanks for the confirmation.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
      If I understand your problem, I can solve it! Of course, the same can be said for you.

Re: An obscure side effect?
by sgifford (Prior) on Aug 03, 2003 at 18:56 UTC

    If you implement your own substr (swab2 below) then you get yet another behavior---it always returns '\0B'---but you can see the order things are being called in. The substr's are evaluated left-to-right and are always working on the original string---it seems to do all of the substr's first, then do the assignments. In that case, you'd get:

      char 0: A ^ B ^ A ^ B = \0
      char 1: B ^ A ^ B     = A
    
    which is what you're seeing. On the other hand, if you use assignments to guarantee the order things are evaluated in (swab3 below), you get the results you'd expect.

    I think you may simply be running into a case where Perl's order of operations is undefined. It can evaluate xor's, substr's, and assignments in any order it feels like, and it doesn't always feel like doing it the same way.

    Here's the code I played with, and the results.

      Interesting. I did think about the order of execution thing, and whether that might be the cause, but then I tried this.

      By redefining swab(), the behaviour goes back to the original, expected result for the first time I call it, with a second and any subsequent calls to the redefined swab() producing erroneous effects.

      Then I tried this

      This shows that both instances of the routine produce the correct result the first time they are called, but then erroneous effects the second time.

      This suggests to me that there is an uninitialised piece of memory being used somewhere that was probably initialised to \0 by the malloc or memset that allocated the larger pool of memory from which it was suballocated, but when the routine is called a second time, the same piece of memory is being reallocated from the same pool, but now has whatever last value it contained. Perhaps it is just a C auto that is being allocated on the stack and happens to have a zero in it the first time it is called, but retains the last value it had the next time it gets used?


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
      If I understand your problem, I can solve it! Of course, the same can be said for you.

        I haven't been able to find any good, solid information about Perl's order of execution for assignment and operand evaluation. If it is the case that the order is undefined in swab, then if Perl wanted to evaluate it one way on Wednesdays and another on Thursdays, unless it was a leap year, that would be perfectly valid...
      I think you may simply be running into a case where Perl's order of operations is undefined.

      Good guess, but a simple experiment disproves it. You can put parentheses around the substr's in the original example to force the order of evaluation.

        Perhaps there's some way to do this, but in general parentheses control the order of evaluation for math operators, not the order of execution for assignments or argument evaluation. For example, how would you parenthesize to make
        $a[$i++] = $i++;
        evaluate the left-hand side before the right, producing $a[0] = 1? Or to make
        $j = $i++ - $i++;
        evaluate the second $i before the first, producing 1?

        How would you suggest parenthesizing in swab to guarantee the order of execution for this?

Re: An obscure side effect?
by fokat (Deacon) on Aug 04, 2003 at 23:51 UTC

    The result on my machine is slightly different:

    bash-2.05a$ perl ./p 'BA' 'BA' 'A' 'A' bash-2.05a$ perl -v | egrep "This is perl" This is perl, v5.8.0 built for darwin bash-2.05a$ uname -a Darwin maclem 6.6 Darwin Kernel Version 6.6: Thu May 1 21:48:54 PDT 2 +003; root:xnu/xnu-344.34.obj~1/RELEASE_PPC Power Macintosh powerpc

    Best regards

    -lem, but some call me fokat

      Thanks. I think the difference is, as Abigail-II noted above, Win32 display drivers tend to represent the null (chr(0)) with a blank glyph on the screen whereas some (all?) *nix DDs 'display' a zero width glyph.

      P:\test>perl -l sub swab{ substr($_[0],$_[1],1)^=substr($_[0],$_[2],1)^=substr($_[0],$ +_[1],1)^=substr($_[0],$_[2],1); } $s='AB'; swab($s,0,1), print "'$s' : ", sprintf "%02x "x2, unpack 'C*',$s for 1 +..10; ^Z 'BA' : 42 41 ' B' : 00 42 ' ' : 00 00 ' ' : 00 00 ' ' : 00 00 ' ' : 00 00 ' ' : 00 00 ' ' : 00 00 ' ' : 00 00 ' ' : 00 00

      As you can see, although they show up as blank glyphs and therefore look like spaces, they are actually nulls.

      I think if you try this on your machine, you'll see that the contents of $s at each stage is the same, it's just the way the nulls get displayed that is different.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
      If I understand your problem, I can solve it! Of course, the same can be said for you.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (8)
As of 2024-04-23 09:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found