Assoziative Arrays erfordern, dass ihre Schlüssel unveränderlich sind. Es macht Sinn, wenn Sie daran denken, dass es sich ändern kann, wenn es nicht unveränderlich ist, was bedeutet, dass sich sein Hashwert ändert, was bedeutet, dass der Computer den Wert nicht mehr finden wird, wenn Sie ihn wieder abrufen. Und wenn Sie es ersetzen, erhalten Sie einen anderen Wert, der dem assoziativen Array hinzugefügt wird (Sie haben also einen mit dem richtigen Hash und einen mit einem falschen Hash). Wenn der Schlüssel jedoch unveränderlich ist, kann er sich nicht ändern, und daher gibt es kein solches Problem.
Vor dmd 2.051 arbeitete das Beispiel (das war ein bug). Es wurde nun behoben, das Beispiel in TDPL ist nicht mehr korrekt. Es ist jedoch nicht so sehr der Fall, dass sich die Regeln für assoziative Arrays geändert haben, da es einen Fehler in ihnen gab, der nicht abgefangen wurde. Das Beispiel kompiliert, wenn es nicht hätte sein sollen, und Andrei hat es verpasst. Es ist in der official errata for TDPL aufgeführt und sollte in zukünftigen Drucken behoben werden. Der korrigierte Code sollte dictionary[word.idup]
oder dictionary[to!string(word)]
verwenden. word.idup
erstellt ein Duplikat von word
, das unveränderlich ist. to!string(word)
, andererseits konvertiert word
zu einem string
in der am besten geeigneten Weise.Da word
in diesem Fall ein char[]
ist, wäre das idup
zu verwenden. Wenn jedoch word
bereits ein string
wäre, würde es einfach den übergebenen Wert zurückgeben und nicht unnötigerweise kopieren. Im allgemeinen Fall ist also to!string(word)
die bessere Wahl (besonders bei Vorlagenfunktionen), aber in diesem Fall funktioniert es entweder gut (to!()
ist in std.conv
).
Es ist technisch möglich, eine char[]
zu einer string
zu werfen, aber es ist im Allgemeinen eine schlechte Idee. Wenn Sie wissen, dass die char[]
wird nie ändern, dann können Sie damit durchkommen, aber im allgemeinen Fall riskieren Sie Probleme, da der Compiler wird dann davon ausgehen, dass die resultierende string
kann nie ändern, und es könnte generieren Code, der falsch ist. Es kann sogar segfault sein. Also, tun Sie es nicht, wenn Profiling zeigt, dass Sie wirklich die zusätzliche Effizienz der Vermeidung der Kopie benötigen, können Sie die Kopie nicht anders vermeiden, indem Sie etwas tun, nur mit einem string
an erster Stelle (so dass keine Konvertierung erforderlich wäre) und Sie wissen, dass die string
wird nie geändert werden.
Im Allgemeinen würde ich nicht zu viel von der Effizienz des Kopierens von Zeichenfolgen sorgen. Im Allgemeinen sollten Sie string
anstelle von char[]
verwenden, damit Sie sie kopieren können (das heißt kopieren Sie ihre Referenz herum (z. B. str1 = str2;
) anstatt ihre gesamten Inhalte wie dup
und idup
zu kopieren), ohne sich darüber Gedanken zu machen, dass sie besonders ineffizient ist. Das Problem mit dem Beispiel ist, dass stdin.byLine()
eine char[]
anstelle einer string
zurückgibt (vermutlich, um das Kopieren der Daten zu vermeiden, wenn es nicht notwendig ist). So gibt splitter()
eine char[]
zurück, und so ist word
eine char[]
anstelle einer string
. Jetzt könnten Sie splitter(strip(line.idup))
oder splitter(strip(line).idup)
anstelle von idup
in den Schlüssel tun. Auf diese Weise würde splitter()
eher eine string
als char[]
zurückgeben, aber das ist wahrscheinlich im Wesentlichen genauso effizient wie idup
ing word
. Unabhängig davon, wo der Text ursprünglich herkommt, ist es eine char[]
anstelle einer string
, die Sie irgendwo entlang der Linie zu zwingt, wenn Sie beabsichtigen, es als Schlüssel in einem assoziativen Array zu verwenden. Im allgemeinen Fall ist es jedoch besser, einfach string
und nicht char[]
zu verwenden. Dann brauchst du nichts zu idup
.
EDIT:
Eigentlich, auch wenn Sie eine Situation, wo char[]
-string
Gießen sicher und notwendig erscheint, sollten Sie mit std.exception.assumeUnique()
(documentation). Es ist im Wesentlichen die bevorzugte Möglichkeit, ein veränderbares Array in ein unveränderliches zu konvertieren, wenn Sie müssen und wissen, dass Sie können. Dies würde normalerweise in Fällen geschehen, in denen Sie ein Array erstellt haben, das Sie nicht unveränderlich machen konnten, weil Sie es in Stücken ausführen mussten, aber keine anderen Referenzen haben, und Sie keine tiefe Kopie davon erstellen möchten. In Situationen wie dem von Ihnen gewünschten Beispiel wäre es jedoch nicht sinnvoll, da Sie das Array wirklich kopieren müssen.
FYI für jeden, der Monate oder Jahre später zu dieser Frage kommt - es gibt andere Dinge, die mit dem gedruckten Beispiel nicht stimmen. Verwenden Sie für den Typ des assoziativen Arrays ulong not uint, und Sie müssen std.array importieren, um den Splitter zu erhalten. Siehe http://www.digitalmars.com/d/archives/digitalmars/D/learn/problems_with_DPL_example._30009.html – DarenW