resultado de std.algorithm.map
Frecuentes
Visto 486 veces
6
¿Alguien podría decir qué std.algorithm.map
¿devoluciones? (se agradecería mucho el enlace a alguna página de documentación) Del mensaje de error su resultado es de tipo Result
ulong[] x = [1,2,3];
ulong[] y = std.algorithm.map!"a"(x); // Error: cannot implicitly convert <..> of type Result to ulong[]
In http://dlang.org/phobos/std_algorithm.html#map hay muy poca información al respecto:
The call map!(fun)(range) returns a range of which elements are obtained by applying fun(x) left to right for all x in range
De esto no está claro, lo que puedo o no puedo hacer con él.
3 Respuestas
7
Se supone que no debes saber o preocuparte por lo que std.algorithm.map
vuelve más allá de que se trata de un rango del mismo género que el pasado (forward, bidireccional, aleatorio, etc.). Es así con la mayoría de las funciones basadas en rango. Casi siempre devuelven un nuevo rango que envuelve el que se pasó o exactamente el mismo tipo de rango que se pasó (por ejemplo, map
hace lo primero; find
hace esto último). Utilizar auto
:
ulong[] x = [1, 2, 3];
auto y = map!"a"(x);
El rango devuelto por map
es perezoso. No hace nada hasta que itera sobre él (luego llama a la función dada en cada sucesiva front
del rango subyacente). Es más eficiente de esa manera (además de permitir rangos infinitos). El tipo de retorno exacto depende del tipo de rango que pasó y es local para map
para que no puedas crear uno directamente. Necesitas usar auto
inferir el tipo o typeof
para obtener el tipo:
typeof(map!"a"(x)) y = map!"a"(x);
Sin embargo, generalmente solo usas typeof
cuando necesita una variable que no puede inicializar directamente. auto
es casi siempre el camino a seguir.
Si necesita crear una matriz a partir del resultado de map
(o de cualquier otro rango), luego use std.array.array
:
ulong[] y = array(map!"a"(x));
Si no sabes mucho sobre rangos, probablemente deberías leer este. Desafortunadamente, actualmente no hay un artículo en dlang.org que explique los rangos, pero ese enlace es para un capítulo en un libro que uno de los miembros de la comunidad D escribió en turco y ha estado traduciendo al inglés, y cubre rangos bastante bien.
EDITAR:
Walter Bright escribió recientemente un artículo específicamente sobre los tipos que son locales para una función pero devueltos por la función que también puede ayudarlo. Incluso tienen un nombre genial: Voldemort Types in D
.
contestado el 11 de mayo de 12 a las 23:05
3
El rango de resultados es 'perezoso', no representa el resultado final.
Se puede convertir en una matriz si importa std.array y la envuelve así:
ulong[] y = array(std.algorithm.map!"a"(x));
or
ulong[] y = std.algorithm.map!"a"(x).array;
si está utilizando dmd 2.059 o posterior
El resultado del mapa también se puede iterar directamente con foreach:
auto result = std.algorithm.map!"a"(x);
foreach (element; result)
writeln(to!string(element));
contestado el 03 de mayo de 12 a las 21:05
@Jonathan Se refiere a la notación de UFCS: reenviar
Ah bien. Entendí mal y pensé que "dmd 2.059 o posterior" se refería a la parte posterior. array
Sin embargo, todavía debería tener parens o no se compilará con -property
(y -property
se supone que eventualmente se convertirá en el comportamiento normal, haciendo que los paréntesis requeridos aquí, ya que array
no es una propiedad). - Jonathan M. Davis
1
Result
es un tipo dentro map()
que no se puede nombrar porque es un Tipo Voldemort.
El actual código fuente en Fobos se ve algo como esto:
template map(fun...) if (fun.length >= 1)
{
auto map(Range)(Range r) if (isInputRange!(Unqual!Range))
{
//...
struct Result
{
//...
}
return Result(r);
}
}
Si estudias el código fuente notarás que Result
no es más que un rango: tiene el habitual popFront()
y empty()
métodos y otros métodos según el tipo de rango que se deba devolver. Si utiliza la inferencia de tipos,
auto r = map!("a*a")(data);
r
se escribirá como Result
, pero no puedes instanciarlo directamente.
contestado el 09 de mayo de 12 a las 17:05
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas types map d or haz tu propia pregunta.
"No se supone que sepas o te importe". Corríjame si me equivoco, pero si no debería saber/importar, entonces mi ejemplo debería compilar: dnsmkl
Quiero decir que no deberías saber o preocuparte porque todo lo que necesitas saber es que es un rango del mismo género que el que se transmitió. El tipo exacto es específico para
map
y no algo que vas a usar. solo usasauto
para inferir el tipo y usar el rango con la API que tienen los rangos. Si desea que sea realmente un tipo específico, debe convertirlo a ese tipo con una función que tome un rango y genere el tipo que desea (p. ej., std.array.array). - Jonathan M. DavisParece antinatural que yo sea forzado de usar
auto
para usar el resultado del mapa (incluso si me gusta la evaluación perezosa y esas cosas) De todos modos, gracias por la respuesta y el enlace: dnsmklBueno, es un tipo con plantilla. e incluso si
map
El tipo de devolución era externo amap
, y podías ver exactamente lo que era, sería demasiado feo para usarlo. En su nivel más básico, seríaMap!(int[])
, y una vez que comienzas a pasar el resultado de una función de rango a otra, los tipos se vuelven realmente feos muy rápido. Por ejemplo, tomauntil
- una de las pocas funciones en std.algorithm cuyo tipo es externo. El tipo deuntil!"a == 7"(intArr)
seríaUntil!("a == 7",int[],void)
. ¿De verdad quieres escribir eso? std.algorithm es muy poderoso, pero sinauto
, bordea lo inutilizable. - Jonathan M. DavisAdemás, generalmente se considera una buena práctica en D usar siempre
auto
a menos que no pueda (por ejemplo, para una declaración de variable que no se inicializa directamente). Entonces, usándolo para el resultado demap
sería lo normal, incluso si devolviera una matriz. - Jonathan M. Davis