http://qs1969.pair.com?node_id=286883

Here's a nice piece of code:

(NO! Don't run it yet :)

$a=$b=$c=1; $a=$a++ + $a++; $b=$b++ + $b; $c=$c + $c++; print "$a $b $c\n";
Meditate a while.

Run the program.

Now, could someone please enlighten me? =)

Replies are listed 'Best First'.
Re: Auto-increment frenzy
by Abigail-II (Bishop) on Aug 26, 2003 at 23:11 UTC
    $a=$a++ + $a++;

    That's undefined behaviour. Pink monkeys might fly out of your nose. Discussing what the output will be is pointless.

    Abigail

      Pink monkeys might fly out of your nose.
      Wow! I didn't realise Perl could do that. There should be some sort of health warning...

      Cheers!

      Pink monkeys might fly out of your nose.
      That's an extreme case, but you always have to beware the HCF instruction when undefined behaviour looms.
Re: Auto-increment frenzy
by BrowserUk (Patriarch) on Aug 27, 2003 at 00:24 UTC

    Whilst the evaluation order is undefined, explaining the behaviour is fairly easy

    P:\test>perl -MO=Deparse,-p $a=$b=$c=1; $a=$a++ + $a++; $b=$b++ + $b; $c=$c + $c++; print "$a $b $c\n"; ^Z ($a = ($b = ($c = 1))); ($a = (($a++) + ($a++))); ($b = (($b++) + $b)); ($c = ($c + ($c++))); print("$a $b $c\n"); - syntax OK

    If you work through unwinding the parens, then you will end up with the correct result. The behaviour is even definable and consistant.

    Explaining why is this way is somewhat harder:)


    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.

      Whilst the evaluation order is undefined

      The behaviour is even definable and consistant

      Those two lines contradict each other.

      perl -MO=Deparse,-p only shows you precedenceorder, not evaluation order. Take for instance

      $a = $a ++ + $a ++;
      The evaluation order might be:
      • Fetch the value of $a, save a copy. (A)
      • Increment the value and store it back in $a.
      • Fetch the value of $a, save a copy. (B)
      • Increment the value and store it back in $a.
      • Add (A) and (B), store the value in $a.
      But it also might be:
      • Fetch the value of $a (A)
      • Fetch the value of $a (B)
      • Add (A) and (B), store the value in $a
      • Increment (A), store it back in $a
      • Increment (B), store it back in $b

      The order of evaluation is UNDEFINED, and therefore, the entire statement is has undefined behaviour.

      And yes, I know the argument, "If I run the program, it always returns XXX". That doesn't say anything. The order in which keys are returned from a hash is undefined as well. If you write a program that inserts the numbers 1 to 100 in a hash, in that order, and then fetches the keys, you will get the same order on each run of the program. Does that mean the order is defined? No, because that fixed order will no longer happen with 5.8.1. Then the order will differ from run to run. And it's safe to introduce that in a maintainance release, because the order in which keys are returned is undefined, even if you think you can predict it.

      Abigail

        Abigail, I think you misspoke. You are indicating that the addition may precede the increments in your second choice.

        Your earlier statement that behaviour is "undefined" is also incorrect. Only the order of evaluation is undefined.

        What is known about:

        $a + $b
        is that both sides will be evaluated before the addition. What is not defined is whether $a or $b will be evaluated first.

        In my example it doesn't matter, but if both terms use and alter the same variables then there can be side effects between the terms.

        Your right Abigail.

        In the scheme of how future perl releases will behave, it is undefined. and is therefore unpredictable. I wasn't disagreeing with this.

        In terms of how any given installation of perl behaves now, then Deparse can illuminate the order in which things are evaluated. And if you inspect a few similar sets of Deparse outputs it becomes predictable how other similar expressions wil be evaluated for that given installation.

        This doesn't remove the risks associated with relying upon the current behaviour, and was not meant to encourage such reliance. Only to explain that behavour and show that it isn't random. Just unwritten and subject to change.


        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: Auto-increment frenzy
by dbp (Pilgrim) on Aug 26, 2003 at 23:02 UTC
    $a = $b = $c = 1; print $a++, " ", $a++, "\n"; print $b++, " ", $b, "\n"; print $c, " ", $c++, "\n";

    Isn't order of operations fun? I'm not sure I completely understand this either. As far as I can tell, although addition is generally left-associative, all operations in the equation (++ operators) are run first. The auto-increment operators have higher precedence than the addition operator. The first two equations in your example are easy to understand. The first $a++ returns 1, which is added to the second $a++ which returns 2, since the inital ++ has already incremented the variable. The $b equation is much the same, since the post-increment operator is superfluous. The final equation is tricky. Because of precedence, the auto-increment runs first, setting the value of the rhs of the equation to 1, and setting $c to 2, which makes that the lhs. Keep in mind, that the addition operator operates on the values returned by the auto-increment operators at the time that they ran.

    Edit: As Abigail-II pointed out, I have no idea what I'm talking about in terms of standards. I am curious, though, why the standards-maintainers chose to keep this behavior undefined.

      Because of precedence, the auto-increment runs first,

      Uhm, no. Now you are confusing operator precedence with evaluation order. Perl does NOT define an evaluation order (for those who want to say "yes, it does", don't do so unless you can cite the documentation saying that Perl does).

      Except for the first line, all lines of code posted by the OP have an undefined behaviour.

      Abigail

Re: Auto-increment frenzy
by belg4mit (Prior) on Aug 27, 2003 at 00:39 UTC
    Interesting, although it might have been more interesting had you given the expect results. I would expect
    1. 3
    2. 3
    3. 2

    --
    I'm not belgian but I play one on TV.

      As long as we are on the subject of expectations, I was expecting:
      1. 5 (the first $a++ assigns 2 to $a, the second $a++ assigns 3, and then $a = 3 + 2). Or the flying pigs out of my nose.
      2. 3
      3. 3
        the first $a++ assigns 2 to $a, the second $a++ assigns 3, and then $a = 3 + 2
        well, I would expect that the post increment actually postincrements:
        $a++ returns $a and increments after that; so the first $a++ returns 1 and now $a is 2, the second increment returns 2 and makes $a = 3
        so the addition returns 1 + 2 = 3.
        He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

        Chady | http://chady.net/
Re: Auto-increment frenzy
by talexb (Chancellor) on Aug 27, 2003 at 21:04 UTC
      Here's a nice piece of code

    I think not.

    Really, this is meandering towards a How many angels can dance on the head of a pin? type debate. It's utterly meaningless.

    More to the point is the following. If $a = 4, then,

    • $b = $a++ means $b will have 4 and $a will have 5.
    • $b = ++$a means $b will have 5 and $a will have 5.
    Anyone who considers doing an increment as part of an expression like $a = $a++ + $a++ should probably become a cruciverbalist or something. It doesn't occur in the real world, really it doesn't. That kind of thing shouldn't even appear on a test (college, university or job-related) either. It's just batty.

    --t. alex
    Life is short: get busy!
      How many angels can dance on the head of a pin?

      Measure pinhead. measure angel's a**. Divide first by second.

      The solution is left as anexercise for the student - R. Heinlein