In D, how can I declare a hash of immutable types that is itself modified?

I believe that I was able to do this in an earlier version of the language, and indeed, the code that I wrote a few months ago, which compiled perfectly, now does not compile. Example:

immutable(X)[int] myhash; myhash[5] = some_immutable_X; //previously fine. myhash[5] = some_other_immutable_X; //previously fine also. 

Now, however, dmd complains about

 Error: cannot modify immutable expression myhash[5] 

I experimented with some other possible syntax without success (for example, (immutable X) [int]). There seems to be no more way to declare that the hash itself is volatile, but the content is not? This seems like a fairly common use case: a data structure for storing links to things that should not be changed. Can anyone figure this out?

+5
source share
3 answers

If it ever worked, it was a mistake (possibly due to the use of void* and incorrect casting somewhere in the implementation of AA, since it was not properly switched to templates, but AFAIK). You cannot mutate immutable values, and when you do

 myHash[5] = value; 

and the elements in myHash are immutable , then you try to change the immutable value even if it is an init value for this type (since the AA element is initialized with the init value before it is assigned, and the type system does not know if the element was previously in AA , therefore, it cannot process the first assignment via [] as initialization, and the rest as the assignment). If you want to have AA elements immutable , then you need a different level of indirection so that the elements themselves are not immutable , but rather relate to something that is immutable - for example, using a mutable pointer to an immutable type, or if you are dealing with classes, use std.typecons.Rebindable (since you cannot have a mutable class linking to const or immutable objects).

+3
source

This behavior did not work until 2.061, it worked from 2.061 to 2.066.1. And this is the “fix” in 2.067.

Additional info: github pull and error issue

+2
source

The easiest way I've found this is to include both an associative array and an element that is modified like this:

 cast()myhash[5] = cast()some_immutable_X; 

I do something similar in my applications, where I initialize immutable definitions loaded from external sources at runtime, and then reference them in mutable objects, so I put a small general example here: http://dpaste.dzfl.pl / 3a4233e5ec82

0
source

All Articles