Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

post-increment and post-decrement behavior (was: dumb question)

by Anonymous Monk
on Mar 16, 2003 at 01:14 UTC ( [id://243392]=perlquestion: print w/replies, xml ) Need Help??

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

how come the output of the middle one prints nothing?

perl -e "print $a++"
0
perl -e "print $a--"

perl -e "print --$a"
-1

Edited 2003-03-19 by mirod: changed the title.

  • Comment on post-increment and post-decrement behavior (was: dumb question)

Replies are listed 'Best First'.
Re: dumb question
by hv (Prior) on Mar 16, 2003 at 03:37 UTC

    Not a dumb question, by any means. I'd say the middle one prints nothing, because $a-- returns the value of $a before the decrement, ie undef. I can think of no good reason, however, for the first to print 0 - that looks like a bug to me.

    Looking at the source, there appears to be some special code in the handling of post-increment to cater for this, and it has been there for a long time - at least as far back as perl5.003. But there isn't any indication of a reason for this special handling, and removing it causes only one test failure that doesn't look to be intentionally testing this feature.

    I've reported this to the perl development mailing list along with a suggested patch to see if anyone has an idea why this special-case should exist.

    Hugo
      I agree that this is a bug. But what is a better fix? I see two different potential fixes, with one common objective to make the interpretation of "print $a--" and "print $a++" consistant.

      1. make both to follow what is happening to post -- now, that is to treat $a as uninitialized, and issue a warining. This might be the only fix for some other languages in a similar case, but not Perl, and I personaly don't like this fix.
      2. Perl is special, and it is not uncommon for Perl to automatically initialize variables for you. Whatever it is post --, or post ++, Perl can predict $a as number, so Perl can just go ahead, and initialize $a to 0. This fix sounds more perlish to me, and I feel that it has a much greater consistancy with the rest part of Perl.

      Try this code:
      $a --; # also try to coment this, and uncomment the next staement #$a ++; print $a; #either -1 or 1, depends on what you uncomment
      In the above demo, whatever it is post --, or post ++, perl would initialied $a to 0, and this is what should happen to print $a-- and print $a++.

        No, #1 is the correct fix. The postdecrement must return the value from before the decrement operation, which is undef.

        In your "fix" #2, how would you handle this situation:

        $a = 'a'; print $a--;

        By your logic, it would also have to print '0', as Perl would predict it to be a number, and after the decrement $a is -1.

        However, I think it is pretty obvious that Perl must print 'a' here.

      Update: after a fascinating debate on the mailing list (though not quite as wide-ranging as the one here:), the existing behaviour has been clarified as deliberate and desirable, and the documentation, code and tests have been amended to reflect that.

      Hugo
Re: dumb question
by jand (Friar) on Mar 16, 2003 at 01:24 UTC
    Because $a is still undef before you decrement it, and undef prints as the empty string. You should consider using the -w option to Perl. The question is, why does the first line print "0"?
      Your suggestion to turn on -w is absolutely right, but we should right the way apply it in this particular case.

      Just a small correction ;-) For $a--, you said, "undef prints as the empty string", that's not quite right. The fact is Perl didn't print anything, and simply ignored that print $a--, because it attempted to print an uninitialized value.

      This would become clear, if you try this:

      Step 1:

      Put this in a file, say test.pl:
      print $a--;
      Step 2:

      Run it by typing perl -w test.pl, and you will get the warning, so perl never printed it as empty string, instead issued a waring. However when you run it as one-liner, the warning is not printed.

      So the bug (inconsistancy) is not that, in the -- case, perl see $a as string; in the ++ case, perl see $a as number.

      The bug (inconsistancy) is that, in the -- case, perl straightly realized $a is uninitialized; in the ++ case, perl initialized it to 0.
        No, that is not correct. Perl still "printed" the undef value as an empty string, it did not abort the print function just because a value was undefined. You could see this with e.g.
        print $a--, "foo";
        to see that you get both the warning and that "foo" is printed. But since printing an empty string is the same as not printing anything, it doesn't make much sense to argue this too long. :)
      Okay, so why does the first one print 0?
        What you are looking at is the difference between post and pre decrement/increment. Note predecrement and preincrement will first do the increment/decrement to the variable and then used. Whereas, postincrement and postdecrement will use the variable first and on the way out increment or decrement. That is:
        print $a++; #prints $a and then increments $a (hence prints 0) print ++$a; #increment $a and THEN print $a (hence prints 1)
        The same can be said of the -- unary operator.

        update:hv++ for answering what was meant (and well, I answered the wrong question)

        -enlil

Re: dumb question
by TimToady (Parson) on Mar 17, 2003 at 17:16 UTC
    Perl is behaving exactly as designed here, and there's no bug--merely an intentional inconsistency. Nobody ever writes $seen{$key}--, whereas they write $seen{$key}++ all the time and expect it not to warn when incrementing an autovivified entry in the hash.

    It would be okay to make the decrement work the same way, but it would really only have the effect of making it run slower.

Re: dumb question
by bsb (Priest) on Mar 17, 2003 at 05:14 UTC
    perlop notes some differences b/w autoinc and autodec
    I'm not sure if it has any bearing on this...

    The auto-increment operator has a little extra builtin magic to it. If you increment a variable that is numeric, or that has ever been used in a numeric context, you get a normal increment. If, however, the vari- able has been used in only string contexts since it was set, and has a value that is not the empty string and matches the pattern "/^a-zA-Z*0-9*\z/", the increment is done as a string, preserving each character within its range, with carry:

    The auto-decrement operator is not magical.

Re: dumb question
by webfiend (Vicar) on Mar 16, 2003 at 13:29 UTC

    Oy. I must remember not to try being helpful before I've drunk my coffee. I just spent 5 minutes trying to get these one-liners to do anything at all, until I remembered Cygwin is sitting on top of DOS and I need to use single quotes :-)


    I just realized that I was using the same sig for nearly three years.

Re: post-increment and post-decrement behavior (was: dumb question)
by Anonymous Monk on Mar 22, 2003 at 19:02 UTC
    Thanks everyone. Knowing that there is special code in the increment op to handle undefs and then an example of perl code why it behaves like this was really useful.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2024-04-26 08:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found