Could somebody say what std.algorithm.map
returns? (link to some documentation page would be very appreciated)
From error message its result is of type 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 there is quite little info on it:
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
From this it is not clear, what I can or can not do with it.
You're not supposed to know or care what std.algorithm.map
returns beyond the fact that it's a range of the same genre as the one passed in (forward, bidirectional, random, etc.). It's that way with most range-based functions. They almost always return either a new range which wraps the one passed in or a the exact same type of range as was passed in (e.g. map
does the former; find
does the latter). Use auto
:
ulong[] x = [1, 2, 3];
auto y = map!"a"(x);
The range returned by map
is lazy. It doesn't do anything until you iterate over it (it then calls the given function on each successive front
of the underlying range). It's more efficient that way (as well as enabling infinite ranges). The exact return type depends on the type of range that you passed in and is local to map
so that you can't create one directly. You need to either use auto
to infer the type or typeof
to get the type:
typeof(map!"a"(x)) y = map!"a"(x);
However, you generally only use typeof
when you need a variable which you cannot initialize directly. auto
is almost always the way to go.
If you need to create an array from the result of map
(or from any other range), then use std.array.array
:
ulong[] y = array(map!"a"(x));
If you don't know much about ranges, then you should probably read this. Unfortunately, there isn't currently an article on dlang.org explaining ranges, but that link is for a chapter in a book which one of the members of the D community wrote in Turkish and has been translating to English, and it covers ranges fairly well.
EDIT:
Walter Bright recently wrote an article specifically about types which are local to a function but returned by the function which may also help enlighten you. They even get a cool name: Voldemort Types in D
.
The Result range is 'lazy', it doesn't represent the final result.
It can be turned into an array if you import std.array and wrap it like so:
ulong[] y = array(std.algorithm.map!"a"(x));
or
ulong[] y = std.algorithm.map!"a"(x).array;
if you are using dmd 2.059 or later
The map result can also be iterated over directly with foreach:
auto result = std.algorithm.map!"a"(x);
foreach (element; result)
writeln(to!string(element));
Result
is a type inside map()
that cannot be named because it is a Voldemort Type.
The actual source code in Phobos looks something like this:
template map(fun...) if (fun.length >= 1)
{
auto map(Range)(Range r) if (isInputRange!(Unqual!Range))
{
//...
struct Result
{
//...
}
return Result(r);
}
}
If you study the source code you will notice that Result
is nothing but a range: it has the usual popFront()
and empty()
methods, and other methods depending on the kind of range that needs to be returned. If you use type inference,
auto r = map!("a*a")(data);
r
will be typed as Result
, but you can't directly instantiate it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With