digitalmars.D.learn - Problem with AAs and ?:
- bearophile (19/19) Mar 08 2008 Can someone explain me where such difference comes from?
- Jarrett Billingsley (7/24) Mar 08 2008 This is odd. Change the body of the first loop to:
- Frits van Bommel (24/45) Mar 08 2008 I looked at the generated code, and it seems that for AA insertions the
- bearophile (4/6) Mar 08 2008 Even if technically it's not a compiler bug, it's seems a bug to me. I l...
Can someone explain me where such difference comes from?
Is this a bug?
import std.stdio: writefln;
void main() {
string[] words = ["how", "are", "you", "are"];
int[string] aa1;
foreach (w; words)
aa1[w] = ((w in aa1) ? (aa1[w] + 1) : 2);
writefln(aa1); // Prints: [how:1,you:1,are:2]
int[string] aa2;
foreach (w; words)
if (w in aa2)
aa2[w]++;
else
aa2[w] = 2;
writefln(aa2); // Prints: [how:2,you:2,are:3]
}
Bye,
bearophile
Mar 08 2008
"bearophile" <bearophileHUGS lycos.com> wrote in message
news:fqu9np$27ic$1 digitalmars.com...
Can someone explain me where such difference comes from?
Is this a bug?
import std.stdio: writefln;
void main() {
string[] words = ["how", "are", "you", "are"];
int[string] aa1;
foreach (w; words)
aa1[w] = ((w in aa1) ? (aa1[w] + 1) : 2);
writefln(aa1); // Prints: [how:1,you:1,are:2]
int[string] aa2;
foreach (w; words)
if (w in aa2)
aa2[w]++;
else
aa2[w] = 2;
writefln(aa2); // Prints: [how:2,you:2,are:3]
}
This is odd. Change the body of the first loop to:
auto val = (w in aa1) ? (aa1[w] + 1) : 2;
aa1[w] = val;
And they both output the same thing (2, 2, 3).
Sorry, breakfast time, I'll look at it a bit more afterwards ;)
Mar 08 2008
bearophile wrote:
Can someone explain me where such difference comes from?
Is this a bug?
import std.stdio: writefln;
void main() {
string[] words = ["how", "are", "you", "are"];
int[string] aa1;
foreach (w; words)
aa1[w] = ((w in aa1) ? (aa1[w] + 1) : 2);
writefln(aa1); // Prints: [how:1,you:1,are:2]
int[string] aa2;
foreach (w; words)
if (w in aa2)
aa2[w]++;
else
aa2[w] = 2;
writefln(aa2); // Prints: [how:2,you:2,are:3]
}
I looked at the generated code, and it seems that for AA insertions the
compiler generates calls an internal routine (_aaGet) which returns a
pointer to the location to put the value into (instead of inserting it
directly). And that call is made *before* the new value is evaluated.
The result is that (w in aa1) evaluates to true because in order to be
able to return that pointer the _aaGet routine allocates the relevant AA
cell if it doesn't exist already; so by the time 'in' is evaluated there
is indeed such a key present (its value just hasn't been set yet).
Essentially, the left side of the assignment is evaluated before the
right side is.
I don't think this is technically a compiler bug with the current the
specification; '=' doesn't determine order of evaluation AFAICT, so the
compiler would seem to have every right to evaluate the left-hand-side
first.
That's probably not what most users would expect, but I can see why this
is done.
The combination of evaluating the right-hand-side of the assignment and
writing it to the AA can in certain situations be more efficient if it's
possible to write the value directly into the AA. (For example: "big"
structs returned from functions are normally written to a
caller-specified address so by evaluating the target location first
"aa[key] = foo()" can pass the AA cell address to the function, which
avoids an extra copy of the struct)
Mar 08 2008
Frits van Bommel:I don't think this is technically a compiler bug with the current the specification; '=' doesn't determine order of evaluation AFAICT,Even if technically it's not a compiler bug, it's seems a bug to me. I like D because it has less surprises than C++. To me a bit less (how much?) running speed is acceptable if similar bugs are avoided by my code. Bye and thank you, bearophile
Mar 08 2008









"Jarrett Billingsley" <kb3ctd2 yahoo.com> 