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