2012-05-03 11 views
6

¿Alguien podría decir qué devuelve std.algorithm.map? (Enlace a alguna página de documentación sería muy apreciado) De mensaje de error su resultado es de tipo Resultresultado de std.algorithm.map

ulong[] x = [1,2,3]; 
ulong[] y = std.algorithm.map!"a"(x); // Error: cannot implicitly convert <..> of type Result to ulong[] 

En http://dlang.org/phobos/std_algorithm.html#map hay bastante poca información sobre ella:

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 es claro, lo que puedo o no puedo hacer con eso.

Respuesta

7

Se supone que no debe saber ni importar qué devuelve std.algorithm.map más allá del hecho de que se trata de un rango del mismo género que el que se pasó (directo, bidireccional, aleatorio, etc.). Es así con la mayoría de las funciones basadas en rango. Casi siempre devuelven un rango nuevo que envuelve el que ingresó o el mismo tipo de rango que se transfirió (por ejemplo, map; el primero; find hace esto último). Utilice auto:

ulong[] x = [1, 2, 3]; 
auto y = map!"a"(x); 

La gama devuelto por map es perezoso. No hace nada hasta que itere sobre él (luego llama a la función dada en cada front sucesivos del rango subyacente). Es más eficiente de esa manera (así como también permite intervalos infinitos). El tipo de devolución exacto depende del tipo de rango que ingresó y es local en map, por lo que no puede crear uno directamente. Es necesario para cualquiera que use auto para inferir el tipo o typeof para obtener el tipo:

typeof(map!"a"(x)) y = map!"a"(x); 

Sin embargo, por lo general sólo se utiliza typeof cuando se necesita una variable que no se 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), a continuación, utilizar std.array.array:

ulong[] y = array(map!"a"(x)); 

Si usted no sabe mucho acerca de rangos, entonces probablemente debería leer this. Desafortunadamente, actualmente no existe un artículo sobre los rangos de explicación de dlang.org, pero ese enlace es para un capítulo de un libro que uno de los miembros de la comunidad D escribió en turco y ha traducido al inglés, y cubre rangos de manera justa. bien.

EDITAR:

Walter Bright escribió recientemente un artículo específicamente acerca de los tipos que son locales a una función, sino que devuelve la función que también puede ayudar a iluminar. Incluso reciben un nombre genial: Voldemort Types in D.

+0

"No se supone que debes saber o preocuparte". Por favor, corrígeme si me equivoco, pero si no lo sé/me importa, entonces mi ejemplo debería compilar – dnsmkl

+1

Quiero decir que no debería saber o preocuparse porque todo lo que necesita saber es que se trata de un rango del el mismo género que el que se pasó. El tipo exacto es específico de '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 desee (por ejemplo, std.array.array). –

+0

Parece antinatural que estoy * forzado * a usar 'auto' para usar el resultado del mapa (incluso si me gusta laizy eval. Y otras cosas) De todos modos, gracias por la respuesta y el enlace – dnsmkl

3

El rango de resultados es 'flojo', no representa el resultado final.

se puede convertir en una matriz si importa std.array y se envuelve este modo:

ulong[] y = array(std.algorithm.map!"a"(x)); 

o

ulong[] y = std.algorithm.map!"a"(x).array; 

si está utilizando DMD 2.059 o posterior

El resultado del mapa también puede repetirse directamente con foreach:

auto result = std.algorithm.map!"a"(x); 
foreach (element; result) 
    writeln(to!string(element)); 
+0

¿Por qué 2.059 o posterior? Eso funcionó por años. –

+0

@Jonathan Él está refiriéndose a la notación de UFCS – fwend

+0

Ah, está bien. Lo malentendí y pensé que el "dmd 2.059 o posterior" se refería a la parte posterior. 'array' en realidad todavía debería tener parens en él o no compilará con' -property' (y '-property' se convertirá en el comportamiento normal eventualmente, haciendo que los parens sean requeridos aquí, ya que' array' no es una propiedad). –

1

Result es un tipo dentro de map() que no se puede nombrar porque es Voldemort Type.

El actual source code 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 se estudia el código fuente se puede observar que Result no es más que una gama: tiene los habituales popFront() y empty() métodos, y otros métodos dependiendo del tipo de rango que necesita ser devuelto. Si utiliza la inferencia de tipos,

auto r = map!("a*a")(data); 

r se escribe como Result, pero no se puede crear una instancia directamente.