Las matrices asociativas requieren que sus claves sean inmutables. Tiene sentido cuando piensas en el hecho de que si no es inmutable, puede cambiar, lo que significa que su hash cambia, lo que significa que cuando vayas a obtener el valor nuevamente, la computadora no lo encontrará. Y si va a reemplazarlo, terminará con otro valor agregado a la matriz asociativa (por lo tanto, tendrá uno con el hash correcto y otro con un hash incorrecto). Sin embargo, si la llave es inmutable, no puede cambiar, por lo que no hay tal problema.
Antes de dmd 2.051, el ejemplo funcionó (que era bug). Ahora se ha corregido, por lo que el ejemplo en TDPL ya no es correcto. Sin embargo, no es tanto el caso de que las reglas para las matrices asociativas hayan cambiado ya que hubo un error en ellas que no fue detectado. El ejemplo compilado cuando no debería y Andrei lo perdió. Se enumera en el official errata for TDPL y se debe corregir en futuras impresiones.
El código corregido debe usar dictionary[word.idup]
o dictionary[to!string(word)]
. word.idup
crea un duplicado de word
que es inmutable. to!string(word)
, por otro lado, convierte word
a string
de la manera más adecuada.Como word
es char[]
en este caso, eso sería usar idup
. Sin embargo, si word
ya fuera un string
, simplemente devolverá el valor que se transfirió y no lo copiará innecesariamente. Por lo tanto, en el caso general, to!string(word)
es la mejor opción (especialmente en funciones con plantilla), pero en este caso, cualquiera de los dos funciona bien (to!()
está en std.conv
).
Es técnicamente posible emitir un char[]
a un string
, pero en general es una mala idea. Si sabe que char[]
nunca cambiará, entonces puede salirse con la suya, pero en el caso general, está arriesgando problemas, ya que el compilador asumirá que el string
resultante nunca puede cambiar, y podría generar código que es incorrecto Incluso puede segfault. Por lo tanto, no lo haga a menos que el perfil demuestre que realmente necesita la eficiencia extra de evitar la copia; de lo contrario, no puede evitar la copia haciendo algo así como simplemente usar un string
(por lo que no sería necesaria ninguna conversión) , y usted sabe que el string
nunca cambiará.
En general, no me preocuparía demasiado la eficacia de la copia de cadenas. Generalmente, debe utilizar string
en lugar de char[]
, de modo que puede copiarlos (es decir, copiar sus referencias (por ejemplo, str1 = str2;
) en lugar de copiar todo su contenido como dup
y idup
) sin preocuparse de que sea particularmente ineficiente. El problema con el ejemplo es que stdin.byLine()
devuelve char[]
en lugar de string
(presumiblemente para evitar copiar los datos si no es necesario). Por lo tanto, splitter()
devuelve char[]
, por lo que word
es char[]
en lugar de string
. Ahora, puede hacer splitter(strip(line.idup))
o splitter(strip(line).idup)
en lugar de idup
ing la clave. De esta forma, splitter()
devolvería string
en lugar de char[]
, pero probablemente sea tan eficiente como idup
ing word
. De todos modos, debido a la procedencia original del texto, es char[]
en lugar de string
, lo que obliga a idup
en algún lugar a lo largo de la línea si tiene la intención de utilizarlo como clave en una matriz asociativa. En el caso general, sin embargo, es mejor usar string
y no char[]
. Entonces no necesita idup
nada.
EDIT:
En realidad, incluso si se encuentra una situación en la fundición char[]
-string
parece a la vez seguro y necesario, considere el uso de std.exception.assumeUnique()
(documentation). Es esencialmente la forma preferida de convertir una matriz mutable a una matriz inmutable cuando lo necesita y sabe que puede hacerlo. Normalmente se realizaría en casos en los que hayas construido una matriz que no podrías hacer inmutable porque tuviste que hacerlo en trozos pero que no tenga otras referencias, y no quieras crear una copia profunda de la misma. Sin embargo, no sería útil en situaciones como el ejemplo sobre el que está preguntando, ya que realmente necesita copiar la matriz.
FYI para cualquiera que llegue a esta pregunta meses o años después - hay otras cosas incorrectas con el ejemplo tal como está impreso. Use ulong not uint para el tipo de matriz asociativa, y necesita importar std.array para obtener el divisor. Consulte http://www.digitalmars.com/d/archives/digitalmars/D/learn/problems_with_DPL_example._30009.html – DarenW