This is an archived low-energy page for bots and other anonmyous visitors.
Please sign up if you are a human and want to interact.
in reply to Re: Incrementing a Hash Value in thread Incrementing a Hash Value
$i = $i ++; Its behaviour is undefined.
It is defined. The ++ operator has nothing to do with this, in Perl. You're right about perlop, and with multiple increments/decrement the order in which things happen is undefined (well, not always. But it is not clear either). But that isn't really what we're dealing with. This is an assignment, just like any $i = EXPR. In this case, EXPR is $i++, which causes $i to be incremented, but returns the old value. The value of EXPR is assigned to $i, so as an end result nothing happens. If $i is tied, FETCH, STORE and STORE are called.
$i = 5;
$i = $i++;
print $i, "\n"; # 5\n
- $i is set to 5
- $i is incremented, new value is 6
- old value (5) is used as the rhs of the assignment operator
- $i is set to that value, old value was 6, new value is 5
- $i and newline are printed
$i = 5;
$i = ++$i;
print $i, "\n"; # 6\n
- $i is set to 5
- $i is incremented, new value is 6
- new value (6) is used as the rhs of the assignment operator
- $i is set to that value, old value was 6, new value is 6
- $i and newline are printed
I have tried this with Perl 5.005 and 5.6.1.
Note: I agree that $i = $i++ is bad style and should never ever be used in non-obfu.
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
Re: Incrementing a Hash Value
by Abigail-II (Bishop) on Jun 14, 2002 at 09:01 UTC
|
This is so utterly wrong, and it's unbelievable that after
so many years, people keep iterating the wrong myths.
Please do provide a pointer to the documentation
that garantees things will happen this way.
All $i ++ is saying that $i
will be incremented after the value is returned. But it
is nowhere specified that $i will be
incremented before or after an assignment. Its
behaviour is UNDEFINED.
(And if you consider this a flame, please take your question
to comp.lang.c (before you say "Perl isn't C", look
up the discussion of ++ in perlop. It
says that it works as in C) and really learn
what being flamed is.)
Abigail | [reply] [d/l] [select] |
|
|
a pointer to the documentation that garantees things will happen this way.
There is none.
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. [...]
If you want guarantees, do not use Perl.
But it is nowhere specified that $i will be incremented before or after an assignment.
$i = $i++ is deparsed to ($i = ($i++)). Having $i tied and assigning to another tied variable tells me the increment happens before the assignment.
look up the discussion of ++ in perlop. It says that it works as in C
Perlop is wrong. Did the authors of Perl re-create all compiler/platform specific postincrement issues that exist in C? If not, how can its behaviour ever be the same?
nowhere specified that $i will be incremented before or after an assignment
perl's sourcecode is the specification - MANY things are not defined in the perldocs. And fortunately, this is compiler/platform independent. Anyway. Here's your specification:
PP(pp_postinc)
{
dSP; dTARGET;
if (SvTYPE(TOPs) > SVt_PVLV)
DIE(aTHX_ PL_no_modify);
sv_setsv(TARG, TOPs);
if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvP
+OK(TOPs)
&& SvIVX(TOPs) != IV_MAX)
{
++SvIVX(TOPs);
SvFLAGS(TOPs) &= ~(SVp_NOK|SVp_POK);
}
else
sv_inc(TOPs);
SvSETMAGIC(TOPs);
if (!SvOK(TARG))
sv_setiv(TARG, 0);
SETs(TARG);
return NORMAL;
}
PP(pp_preinc)
{
dSP;
if (SvTYPE(TOPs) > SVt_PVLV)
DIE(aTHX_ PL_no_modify);
if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvP
+OK(TOPs)
&& SvIVX(TOPs) != IV_MAX)
{
++SvIVX(TOPs);
SvFLAGS(TOPs) &= ~(SVp_NOK|SVp_POK);
}
else /* Do all the PERL_PRESERVE_IVUV conditionals in sv_inc */
sv_inc(TOPs);
SvSETMAGIC(TOPs);
return NORMAL;
}
Pay special attention to dTARGET, sv_setsv and SETs in the postinc. As you can see, Perl does not delay the increment, but it does save the old value. (Which is because Perl can not optimise the same way C compilers do. At compile time, Perl cannot be sure if $i is a normal scalar or something special.)
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] [d/l] [select] |
|
|
The fact that it deparses as ($i = ($i++))
does not say anything. It still will not say anything about
the order in which the assignment and the increment are done.
Did the authors of Perl re-create all compiler/platform specific postincrement issues that exist in C?
Why should they? All they had to do was follow the specifications.
And the specification say that the code we are talking about
has undefined behaviour.
MANY things are not defined in the perldocs.
And are hence subject to change without a deprecation cycle.
Even the smallist patch might radically change the behaviour,
including attempts to erase all the files from your disk.
That's the nature of undefined behaviour.
Abigail
| [reply] [d/l] |
|
|
|
|
| |
|
| |
|
Re: Re: Re: Incrementing a Hash Value
by dsheroh (Monsignor) on Jun 14, 2002 at 14:12 UTC
|
(I really should know better than to walk into this
firestorm, but I just can't help myself...)
The two of you obviously mean different things by "defined".
Abigail says that $i = $i++ is undefined
because it is not declared in the Perl (or C) language
specs. Juerd says that it is defined because it has
consistently behaved in the same way for as long as anyone
can remember.
In my experience, Abigail's definition of definedness is the
one most commonly (and, many would argue, most properly)
used in this context. While the behaviour of
$i = $i++ may be deterministic, the
fact remains that its behaviour is merely an artifact of
how it is implemented and should not be relied upon,
because, without any implementation-independent
specification of its behaviour,
next release of perl is free to arbitrarily change it for
any reason (or no reason at all). | [reply] [d/l] [select] |
Re: Re: Re: Incrementing a Hash Value
by Elian (Parson) on Jun 14, 2002 at 14:48 UTC
|
Proof by experimentation's not valid for programming languages. Bad, bad idea. (This isn't physics here--the rules of the universe are subject to change from version to versions) Only what the standard, or the documentation, guarantees is valid to count on. Everything else should be considered a quirk of the implementation.
This bit, in particular, could easily be changed with a small cahnge to the optimizer, or optree generator. That it hasn't happened is mainly because nobody's bothered. (Well, because that part of the code's reasonably scary) Because of the way that perl works internally, both the pre and post increment versions of that code could easily resolve to 6.
Trust Abigail here. Don't count on the behaviour of multiple manipulations to a variable without an intervening sequence point. | [reply] |
|
|
Only what the standard, or the documentation, guarantees is valid to count on. Everything else should be considered a quirk of the implementation.
Shouldn't there be a lot more documentation, then? Increments and decrements are not the only things being documented vaguely.
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] |
|
|
$a = $a + $a++;
what should $a equal at the end? And if $a is tied or overloaded, what order should the tie/overload stuff be called in? | [reply] [d/l] |
|
|