www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - An incorrect associative array work?

reply Dark Hole <dark.hole1 yandex.ru> writes:
Let's take a look at this code:

int[char[]] test;
char[4] buf = "abcd";
test[buf] = 1;
buf = "evil";
writeln(test);

What we're expecting to see:
["abcd":1]
But real result is:
["evil":1]

But if we replace static array with dynamic, we'll get error "key 
must be immutable". Not exactly what we expected, but ok. If we 
declare test as int[char[4]], it works as expected.

So, is this behaviour bug?
Sep 19 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/19/20 3:38 PM, Dark Hole wrote:
 Let's take a look at this code:
 
 int[char[]] test;
 char[4] buf = "abcd";
 test[buf] = 1;
 buf = "evil";
 writeln(test);
If you print typeof(test), you will see: int[const(char)[]]. In other words, the compiler has modified the type you asked for into one that accepts const keys. I hate this aspect of AAs, a const key is no better than a mutable key, as mutable keys convert implicitly to const!
 What we're expecting to see:
 ["abcd":1]
 But real result is:
 ["evil":1]
What is happening is that you replaced the key data, and the char[4] implicitly casts to a dynamic array (another horrible aspect of D). If you tried to access test["abcd"] OR test["evil"] you would get a range error. If you returned from this function, you now have a dangling pointer. This code is all kinds of bad, it shouldn't compile.
 But if we replace static array with dynamic, we'll get error "key must 
 be immutable".
Hilarious. I don't even know where that error comes from, but it's totally incorrect. Both the error text is incorrect (it doesn't only accept immutable keys) and the fact that the key type is const means the mutable value should really bind to const. Add on to that but it ACCEPTED the mutable char[4] as a key! As a demo, try this out: char[] buf = "abcd".dup; const b = buf; test[b] = 1; buf[] = "evil"; Now, same exact result. Which is why we really should either accept mutable keys and allow whatever happens to happen, or accept ONLY immutable or value-types as keys.
 Not exactly what we expected, but ok. If we declare test 
 as int[char[4]], it works as expected.
Now THIS is more correct -- a char[4] is a value type, not a reference type. And so when you use it as a key, it makes a COPY to store in the associative array. So it works as designed. I highly recommend either using strings as keys, or using value types.
 
 So, is this behaviour bug?
Yes, I think there are several. And I believe they are all in bugzilla, but don't have the time to look right now. -Steve
Sep 19 2020