resultado de std.algorithm.map

¿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.

preguntado el 03 de mayo de 12 a las 19:05

3 Respuestas

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

"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 usas auto 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. Davis

Parece 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: dnsmkl

Bueno, es un tipo con plantilla. e incluso si mapEl tipo de devolución era externo a map, y podías ver exactamente lo que era, sería demasiado feo para usarlo. En su nivel más básico, sería Map!(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, toma until - una de las pocas funciones en std.algorithm cuyo tipo es externo. El tipo de until!"a == 7"(intArr) sería Until!("a == 7",int[],void). ¿De verdad quieres escribir eso? std.algorithm es muy poderoso, pero sin auto, bordea lo inutilizable. - Jonathan M. Davis

Ademá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 de map sería lo normal, incluso si devolviera una matriz. - Jonathan M. Davis

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

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 or haz tu propia pregunta.