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
| [reply] [d/l] [select] |
|
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.
- 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.
- 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++. | [reply] [d/l] |
|
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. | [reply] [d/l] |
|
|
|
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
| [reply] |
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"? | [reply] |
|
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. | [reply] [d/l] |
|
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. :) | [reply] [d/l] |
|
|
|
|
|
Okay, so why does the first one print 0?
| [reply] |
|
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 | [reply] [d/l] |
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. | [reply] [d/l] [select] |
Re: dumb question
by bsb (Priest) on Mar 17, 2003 at 05:14 UTC
|
| [reply] |
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.
| [reply] |
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. | [reply] |