Problem with AAs and ?:

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Sat Mar 8 09:16:36 PST 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)


More information about the Digitalmars-d-learn mailing list