Re: Incrementing a Hash Value
by Abigail-II (Bishop) on Jun 14, 2002 at 10:57 UTC
|
$i = $i ++;
DO NOT DO THAT.
Now you have an expression in which you are modifying
$i twice. It's behaviour is undefined.
If you want to increment the value, just use:
thes_name {$fields [1]}++;
That's all.
Abigail
| [reply] [d/l] [select] |
|
Is it undefined, or does do this:
# basic form
$i = $i++;
# long hand
$k = $i;
$i++;
$i = $k;
--
¤ Steve Marvell | [reply] [d/l] |
|
| [reply] [d/l] |
|
|
Is it undefined, or does do this: $k = $i; $i++; $i = $k;
Both.
$i++ stores the old value, increases the value, and then sets the return value to the stored old value. Although that is true for all versions of Perl, its behaviour is not documented. Actually, it is documented, but wrong:
[...] increment or
decrement the variable after returning the value. [...] -- perlop
It doesn't increment after returning. It increments first, and then returns the old value.
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] |
|
A reply falls below the community's threshold of quality. You may see it by logging in.
|
|
|
|
|
$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.
| [reply] [d/l] [select] |
|
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] |
|
|
|
(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] |
|
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] |
|
|
|
|
Why is this difficult to grasp? It seems like good common sense to me.
()-()
\"/
`
| [reply] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: Incrementing a Hash Value
by marvell (Pilgrim) on Jun 14, 2002 at 10:54 UTC
|
Try simply:
$thes_name{$fields[1]}++;
--
Steve Marvell | [reply] [d/l] |
Re: Incrementing a Hash Value
by Sifmole (Chaplain) on Jun 14, 2002 at 11:05 UTC
|
marvell has a correct answer for you. I wanted to explain for you why your choice was not working.
// I am making the assumption that the syntax
// error here is just a typo ( missing a $ in front
// of the second thes_name) .
$thes_name{$fields[1]} = thes_name{$fields[1]}++;
What this code does is effectively the following:
Start) $thes_name{$fields[1]} has a value of 1
1) Resolves $thes_name{$fields[1]} to its value "1".
2) Increments $thes_name{$fields[1]} to "2"
3) Sets $thes_name{$fields[1]} to the previously resolved value, "1".
End) Thus $thes_name always stays at "1".
Because you used a "post-increment" it happens after the variable is already resolved. If you had used a "pre-increment", ++$thes_name{$fields[1]}, if would have done what you expected -- but marvells answer for that is better. | [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
And with some compilers and some versions of Perl it will work on some platforms for some values of the hash.
Compilers and platforms have absolutely nothing to do with the order in which Perl walks its ops.
Perl code (code written in Perl) is not compiled by a C compiler.
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] |
A reply falls below the community's threshold of quality. You may see it by logging in.
|
Re: Incrementing a Hash Value
by Juerd (Abbot) on Jun 14, 2002 at 17:34 UTC
|
$thes_name{$fields[1]} = thes_name{$fields[1]}++;
This being a no-op, and all postincrement stuff aside, you're missing a $ before thes_name.
19:29 < ua> did anyone bother mentioning to the guy that he was missing a '$'
in his postdec?
(No, just placing the $ there won't do what you want. The correct example has already been given.)
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] [d/l] |