saurabh.hirani has asked for the wisdom of the Perl Monks concerning the following question:

Hi guys,

A friend of mine had just asked an interesting question about increment, decrement operators which led to my query.

What should be the output of
perl -le '$a = 10; $a++ + $a--'

It should be 21 instead of 20 because if I were to think how the calculation would be done - convert to postfix, push operands on stack till operator is encountered, when operator encountered, pop out 2 operands and perform operation and push result onto stack:

  1. Push value of $a - 10 on stack
  2. Increment $a by 1 - 11
  3. Push value of $a - 11 on stack
  4. Increment $a by 1 - 12
  5. Pop out 10, 11 perform addition

A similar explanation can be done for:

perl -le '$a = 10; $a++ + $a--'
perl -le '$a = 10; $a++ + $a-- + $a-- + $a--'

Can you guys please tell me how would the postfix calculation progress in case of

perl -le '$a = 10; print $a++ + ++$a;'
and
perl -le '$a = 10; print ++$a + $a++;'

I don't know why the result of ++$a + $a++ turned out to be 23.

Thanks for going through,

Replies are listed 'Best First'.
Re: Prefix and postfix increment/decrement operator query
by davorg (Chancellor) on Jul 02, 2009 at 12:22 UTC

    From perlop:

    Note that just as in C, Perl doesn't define when the variable is incremented or decremented. You just know it will be done sometime before or after the value is returned. This also means that modifying a variable twice in the same statement will lead to undefined behaviour. Avoid statements like:

    $i = $i ++; print ++ $i + $i ++;

    Perl will not guarantee what the result of the above statements is.

    "Undefined behaviour" means "anything could happen".

    --

    See the Copyright notice on my home node.

    Perl training courses

      This explanation is very close. 'C' is very well defined about what is does in terms of statements with lvalues. 'C' is also explicitly ambiguous about what it does with subroutine parameters - in subroutine call, there is NO defined order of evaluation of expressions in the sub call: sub a(expr1, expr2)! C can do expr1 first or expr2 first. Often in C expr2 will be done first because that is the first value that will be pushed onto the calling stack. But there is nothing that mandates that or prohibits a different order. I seem to remember from a discussion with a higher Monk (Ikegami) that Perl always goes left to right, even in a sub arg evaluation, but I also seem to remember that this is not guaranteed by the language spec and therefore I wouldn't count on it.

      I have to mention that $i=$i++ or in C i=i++ is nonsensical. "i" gets assigned back to "i" and then "i" gets incremented and that value is "thrown away".

      In my opinion, a lexically scoped $var is a very cheap thing and should be used if there is any doubt about some subsequent statement. I'm not advocating creating extra unnecessary vars, just ones that "add clarity".

        In my opinion, a lexically scoped $var is a very cheap thing and should be used if there is any doubt about some subsequent statement. I'm not advocating creating extra unnecessary vars, just ones that "add clarity".

        I agree with you. I had posted this query because I thought about the expression behaving in a certain manner but it didn't. So it was pure curiosity. Thanks for that addition. I too wouldn't use such ambiguity in my work.

Re: Prefix and postfix increment/decrement operator query
by wfsp (Abbot) on Jul 02, 2009 at 12:23 UTC
Re: Prefix and postfix increment/decrement operator query
by ikegami (Pope) on Jul 02, 2009 at 17:08 UTC

    Officially, the behaviour is undefined. The following documents what actually happens. It boils down to the fact that pre-increments and pre-decrements leave the input variable on the stack while post-increments and post-decrements leave a copy of it.

    $a++ + ++$a $a Stack 1. Push copy of $a on stack 10 10 2. Increment $a 11 10 3. Increment $a 12 10 4. Push $a on stack 12 10,$a 5. Add 12 22
    ++$a + $a++ $a Stack 1. Increment $a 11 2. Push $a on stack 11 $a 3. Push copy of $a on stack 11 $a,11 4. Increment $a 12 $a,11 5. Add 12 23

    Note: These steps don't correspond one-for-one to the ops actually involved for the sake of simplicity.

      $a Stack 1. Push copy of $a on stack 10 10 2. Increment $a 11 10 3. Increment $a 12 10 4. Push $a on stack 12 10,$a 5. Add 12 22
      ++$a + $a++ $a Stack 1. Increment $a 11 2. Push $a on stack 11 $a 3. Push copy of $a on stack 11 $a,11 4. Increment $a 12 $a,11 5. Add 12 23

      Thanks for a very clear explanation. I appreciate that.

Re: Prefix and postfix increment/decrement operator query
by ack (Deacon) on Jul 02, 2009 at 15:10 UTC

    Looks like your answer was very well covered by the other responders. Mine is just a nit since I think I know what you meant; but you said in your post:

    "It should be 21 instead of 20 because..."

    Did you mean "...11 instead of 10..." since you initialize your variable to 10 rather than to 20?

    ack Albuquerque, NM
      Did you mean "...11 instead of 10..." since you initialize your variable to 10 rather than to 20?

      I was talking about the answer of the operation $a++ + $a--. But yes, as per your observation.the value of $a should be 11 instead of 10.

Re: Prefix and postfix increment/decrement operator query
by JavaFan (Canon) on Jul 02, 2009 at 12:26 UTC
    What should be the output of
    perl -le '$a = 10; $a++ + $a--'
    Nothing of course! You aren't doing any I/O, so if your perl emits anything, it's broken!

    Now, if you mean, "what is the value of $b after $a = 10; $b = $a++ + $a--?", then I suggest you RTFM instead of starting the same heated debate which runs through Perlmonks a few times a year.

    Just RTFM. Then, if any question remains, come back.

      @JavaFan - I meant -

      perl -le '$a = 10; print $a++ + $a--'

      Sorry for missing out on the print statement.

      Thanks davorg, wfsp for pointing to perlop and the Autoincrement magic link. I guess as it is undefined behavior I will leave it at that.