2015-04-29 7 views
5

Ich glaube, ich war in der Lage, dies in einer früheren Version der Sprache zu tun, und in der Tat, Code, den ich vor einigen Monaten geschrieben, die kompiliert dann gut, kompiliert jetzt nicht. Beispiel:Wie kann ich in D einen Hash von unveränderlichen Typen deklarieren, der selbst veränderbar ist?

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

Jetzt aber DMD klagt mit

Error: cannot modify immutable expression myhash[5] 

Ich habe mit einigen anderen möglichen Syntax ohne Erfolg experimentiert (z (unveränderlich X) [int]). Es scheint, dass es keinen Weg mehr gibt zu erklären, dass der Hash selbst veränderbar ist, aber der Inhalt nicht? Dies scheint ein ziemlich verbreiteter Anwendungsfall zu sein: eine Datenstruktur zum Speichern von Verweisen auf Dinge, die nicht verändert werden sollten. Hat jemand einen Einblick in das?

+0

Ist X-Wert oder ein Referenztyp (dh Klasse)? –

+0

Funktioniert nicht mit keiner, aber funktioniert gut mit 2.066.1 und vor – Kozzi11

+0

X ist eine Klasse (d. H. Eine Referenz). –

Antwort

3

Wenn es jemals gearbeitet, es war ein Fehler (wahrscheinlich aufgrund der Verwendung von void* und falschem Gießen irgendwo in der AA-Implementierung, da es nicht eingeschaltet ist richtig Vorlagen noch AFAIK). Sie können nicht immutable Werte mutieren, und wenn Sie

tun
myHash[5] = value; 

und die Elemente in myHash sind immutable, dann Sie versuchen, ein immutable Wert zu mutieren, auch wenn es der init Wert für diesen Typ ist (da ein AA-Element bekommt initialisiert mit dem init Wert, bevor es zugewiesen ist, und das Typsystem hat keine Möglichkeit zu wissen, ob das Element zuvor in der AA war, so kann es nicht die erste Zuweisung über [] als Initialisierung und die anderen als Zuweisung behandeln). Wenn Sie ein AA von immutable Elemente haben wollen, dann werden Sie eine andere Ebene der Indirektion benötigen, so dass die Elemente selbst nicht immutable sind, sondern eher auf etwas verweisen, das immutable ist - zB durch Verwendung eines veränderbaren Zeigers auf einen immutable Typ, oder wenn Sie mit Klassen arbeiten, verwenden Sie std.typecons.Rebindable (da Sie keine veränderbaren Klassenreferenzen auf const oder immutable Objekte haben können).

2

Dieses Verhalten hat nicht vor 2.061 funktioniert, es wurde von 2.061 bis 2.066.1 gearbeitet. Und es ist "fix" in 2.067.

Weiteren Informationen: github pull und bug issue

0

Die einfachste Art, wie ich es während des Einsetzens, wie so sowohl das assoziative Array und das Element zu wandelbar zu werfen, war, gefunden:

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

ich so etwas in meinen Anwendungen, bei denen ich initialisieren unveränderliche Definitionen geladen von externen Quellen zur Laufzeit und dann referenzieren sie in veränderlichen Einheiten, so dass ich ein kleines generisches Beispiel hier: http://dpaste.dzfl.pl/3a4233e5ec82