Re: FAQ 4.47 How do I handle circular lists?
- From: "Peter J. Holzer" <hjp-usenet2@xxxxxx>
- Date: Sat, 17 May 2008 14:50:21 +0200
On 2008-05-14 09:09, sheinrich@xxxxxxxxxxx <sheinrich@xxxxxxxxxxx> wrote:
On May 13, 3:11 pm, "John W. Krahn" <some...@xxxxxxxxxxx> wrote:
sheinr...@xxxxxxxxxxx wrote:
$index = ++$index % $asize;
perldoc perlop
[ SNIP ]
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.
So don't do that. Do this instead:
$index = ( $index + 1 ) % $asize;
"You just know it will be done sometime before or after the value is
returned."
I've been reading that as 'sometime before' in case of a preincrement,
'after' for a postincrement.
In which case my
$index = ++$index % $asize;
looks fairly safe.
It may not be.
IMHO the expression above can result in an error only, if the
increment is first computed and returned and is assigned to $index
only after the modulo operation or even after the explicit assignment.
Right. The compiler could produce something like:
$tmp1 = $index + 1
$tmp2 = $tmp1 % $asize
$index = $tmp2
$index = $tmp1
You may be right in that this can really happen. But then it's a very
strange behaviour indeed.
Not that strange for compilers which produce code for real CPUs (which
often have very strange timing requirements). I wouldn't really expect
it from a simple bytecode-generating compiler like perl's.
The warning that the execution order is undefined comes from C. But in C
this is a consequence of the concept of "sequence points". The language
defines certain points (e.g., the end of each statement, each function
call, etc.) where each previous operation must be finished and no
subsequent operation must have begun. between two sequence points the
compiler can reorder operations at will. There are two rules about
modifying values:
1) You can modify an object[1] only once between two sequence points
2) If you modify an object, you can only read it to compute the new
value.
But Perl doesn't have the concept of sequence points, and there is no
general prohibition agains modifying the same object twice in a
statement, just against using the increment and decrement operators.
That does stand out as an odd exception. IMHO Perl should either define
an execution order (which could be a partial order) or adopt a more
generic concept like that of C.
I've been using the autoincrement out of habit and for performance
considerations
Surprisingly,
$index = ++$index % $asize;
is really about 40 % faster than
$index = ( $index + 1 ) % $asize;
I had not expected this. Apparently creating a constant IV is a
relatively expensive operation (well, it takes about 36 nanoseconds on
my PC, so "relatively expensive" is, er, relative).
hp
.
- Follow-Ups:
- Re: FAQ 4.47 How do I handle circular lists?
- From: sheinrich
- Re: FAQ 4.47 How do I handle circular lists?
- References:
- FAQ 4.47 How do I handle circular lists?
- From: PerlFAQ Server
- Re: FAQ 4.47 How do I handle circular lists?
- From: sheinrich
- Re: FAQ 4.47 How do I handle circular lists?
- From: John W. Krahn
- Re: FAQ 4.47 How do I handle circular lists?
- From: sheinrich
- FAQ 4.47 How do I handle circular lists?
- Prev by Date: Re: Strawberry
- Next by Date: FAQ 4.33 How do I pad a string with blanks or pad a number with zeroes?
- Previous by thread: Re: FAQ 4.47 How do I handle circular lists?
- Next by thread: Re: FAQ 4.47 How do I handle circular lists?
- Index(es):
Relevant Pages
|