To date, I've been using D in much the same way I used C++, without heavy
use of templates. Now I'm trying out a more functional style using
std.algorithm. However I'm pretty much stuck at the first hurdle: map.

Welcome to functional D :-)

The most general interfaces I can see are InputRange(E) and OutputRange(E).

In D language there is about as much support for OOP as in Java (and more), but
in practice OO interfaces are not used significantly in the D standard library.
So those are a different kind of "interfaces", they are a bit more like C++0x
Concepts, they are very statically typed. So while they are organized in a
hierarchy, you can't assign them as OO interfaces.
You generally use type inference to assign the type of map. In functional
programming a bit of type inference is not optional, it's almost needed.
map() in D is lazy, it doesn't return an array, but a lazily iterable range. If
you want an eager dynamic array you may use array():
array(map!((a) { return a * a; })(start));
If you don't want to use type inference for the return result of map, you have
to take a look at the source code of std.functional, read what type is exactly
map, and copy it. Generally this is not done in normal user code.
Bye,
bearophile

To date, I've been using D in much the same way I used C++, without heavy
use of templates. Now I'm trying out a more functional style using
std.algorithm. However I'm pretty much stuck at the first hurdle: map.
With type inference, this works:
import std.algorithm;
import std.stdio;
void main() {
auto start = [1,2,3,4,5];
auto squares = map!((a) { return a * a; })(start);
writeln(squares);
}
Without type inference (obviously necessary beyond trivial examples),

Type inference is useful everywhere, at any level of complexity.
Where it's not useful is declarations, for example, declaring the type of
a struct or class member. However, typeof should work to use type
inference there.

OK, so this is kind of a weird case. std.algorithm.map returns an inner
struct, which means, it has no public name. But then how can you even use
it? Well, it just doesn't have a public *name*, but it still can be used
outside the function. It's definitely an oddball. However, what's nice
about it is that you can encapsulate the struct inside the one place it is
used.
You can see the definition of map here:
https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm.d#L366
And a few lines down, the declaration of Result.
You can use typeof if you want to get the type, but again, auto is much
better unless you are declaring something.

However, they do tell me that map "returns a range". Assuming all
definitions of ranges are in std.range, there's no such thing as a
"Range"
interface, so it's not that. The most general interfaces I can see are
InputRange(E) and OutputRange(E). It certainly can't be an OutputRange,
so
I guess it must satisfy InputRange, presumably type-parameterized with
"int".

No, a range is a concept, meaning it is a compile-time interface. Any
type which satisfies the requirements of the input range can be a range,
even non-polymorphic types. Even an array is a range.

Right, because it's not a derivative of that interface, it's its own type,
defined only inside the function. Yeah, I know it's confusing :)

That's weird, because "std.range.InputRange!(int).InputRange" doesn't
even
look like a type.

std.range is the module, but I assume you already know that.
But one of the coolest things about D templates is the eponymous rule.
That is, if you declare a template, and that template has exactly one
member, and that one member is named the same as the template, then x!(y)
becomes the equivalent of x!(y).x.
For example:
template t(T)
{
class t
{
T val;
}
}
t!(int) is equivalent to t!(int).t
In other words, a template is a *namespace* for declarations using the
template parameters. And in this special case, you can omit the member of
the namespace you are accessing.
Then what follows is that:
class t(T)
{
T val;
}
is shorthand for the above.
But the compiler maintains the namespace.member nomenclature, which is why
you see that in the error message.
-Steve

Type inference is useful everywhere, at any level of complexity.
Where it's not useful is declarations, for example, declaring the type of a
struct or class member. However, typeof should work to use type inference
there.
it'd

OK, so this is kind of a weird case. std.algorithm.map returns an inner
struct, which means, it has no public name. But then how can you even use
it? Well, it just doesn't have a public *name*, but it still can be used
outside the function. It's definitely an oddball. However, what's nice
about it is that you can encapsulate the struct inside the one place it is
used.
You can see the definition of map here: https://github.com/D-**
Programming-Language/phobos/**blob/master/std/algorithm.d#**L366<https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm.d#L366>
And a few lines down, the declaration of Result.
You can use typeof if you want to get the type, but again, auto is much
better unless you are declaring something.
However, they do tell me that map "returns a range". Assuming all

definitions of ranges are in std.range, there's no such thing as a "Range"
interface, so it's not that. The most general interfaces I can see are
InputRange(E) and OutputRange(E). It certainly can't be an OutputRange,
so
I guess it must satisfy InputRange, presumably type-parameterized with
"int".

No, a range is a concept, meaning it is a compile-time interface. Any type
which satisfies the requirements of the input range can be a range, even
non-polymorphic types. Even an array is a range.
So this should work:

Right, because it's not a derivative of that interface, it's its own type,
defined only inside the function. Yeah, I know it's confusing :)
That's weird, because "std.range.InputRange!(int).**InputRange" doesn't

even
look like a type.

std.range is the module, but I assume you already know that.
But one of the coolest things about D templates is the eponymous rule.
That is, if you declare a template, and that template has exactly one
member, and that one member is named the same as the template, then x!(y)
becomes the equivalent of x!(y).x.
For example:
template t(T)
{
class t
{
T val;
}
}
t!(int) is equivalent to t!(int).t
In other words, a template is a *namespace* for declarations using the
template parameters. And in this special case, you can omit the member of
the namespace you are accessing.
Then what follows is that:
class t(T)
{
T val;
}
is shorthand for the above.
But the compiler maintains the namespace.member nomenclature, which is why
you see that in the error message.
-Steve

So ... stuff works, but I'm not really sure why one uses function
templating and the other uses return type inference. Any answers?

... Wait, brain malfunction; I think I do understand. The type is
inferable
purely from the function definition in the latter case.

Yes, the return type is determined by the return statement in the function
itself. Note that it would be an error to have two different return types
that compiled into the same function. A frequent use of auto is when the
return type could be different based on template parameters to the
function, or version statements. In these cases, effectively there is
only one return type, because only one return statement gets compiled.
The reason your getSquares(T)() *call* doesn't work is because the
compiler first must instantiate the template, and it doesn't have enough
information to do so. Remember that a function template like this:
T getSquares(T)() {...}
is equivalent to this:
template getSquares(T)
{
T getSquares() {...}
}
So in fact, the compiler cannot evaluate the inner part of the template
until it knows what T is. However, there is a special feature called
implicit function template instantiation (IFTI) which allows the compiler
to infer the values of T from the function call being made. This means
the types of arguments to the function can be used to infer the template
parameters. This *only* works for template functions or templates that
can be reduced to template functions.
So for example:
T foo(T)(T t) {return t;}
you can call this function via:
foo(1);
And T will implicitly be assigned int.
But since your getSquares function takes no parameters, IFTI cannot be
used. Note that the return type does NOT play a role in IFTI.
However, you can still use getSquares, just specify the template parameter
explicitly:
auto sq = getSquares!int();
Another option is to give a default value for T:
T getSquares(T = int)() {...}
-Steve

So ... stuff works, but I'm not really sure why one uses function
templating and the other uses return type inference. Any answers?

... Wait, brain malfunction; I think I do understand. The type is
inferable
purely from the function definition in the latter case.

Yes, the return type is determined by the return statement in the function
itself. Note that it would be an error to have two different return types
that compiled into the same function. A frequent use of auto is when the
return type could be different based on template parameters to the function,
or version statements. In these cases, effectively there is only one return
type, because only one return statement gets compiled.
The reason your getSquares(T)() *call* doesn't work is because the compiler
first must instantiate the template, and it doesn't have enough information
to do so. Remember that a function template like this:
T getSquares(T)() {...}
is equivalent to this:
template getSquares(T)
{
T getSquares() {...}
}
So in fact, the compiler cannot evaluate the inner part of the template
until it knows what T is. However, there is a special feature called
implicit function template instantiation (IFTI) which allows the compiler to
infer the values of T from the function call being made. This means the
types of arguments to the function can be used to infer the template
parameters. This *only* works for template functions or templates that can
be reduced to template functions.
So for example:
T foo(T)(T t) {return t;}
you can call this function via:
foo(1);
And T will implicitly be assigned int.
But since your getSquares function takes no parameters, IFTI cannot be
used. Note that the return type does NOT play a role in IFTI.
However, you can still use getSquares, just specify the template parameter
explicitly:
auto sq = getSquares!int();
Another option is to give a default value for T:
T getSquares(T = int)() {...}
-Steve

<br>
The reason your getSquares(T)() *call* doesn&#39;t work is because the comp=
iler first must instantiate the template, and it doesn&#39;t have enough in=
formation to do so. =C2=A0Remember that a function template like this:<br>
<br>
T getSquares(T)() {...}<br>
<br>
is equivalent to this:<br>
<br>
template getSquares(T)<br>
{<br>
=C2=A0 T getSquares() {...}<br>
}<br>
<br>
So in fact, the compiler cannot evaluate the inner part of the template unt=
il it knows what T is. =C2=A0However, there is a special feature called imp=
licit function template instantiation (IFTI) which allows the compiler to i=
nfer the values of T from the function call being made. =C2=A0This means th=
e types of arguments to the function can be used to infer the template para=
meters. =C2=A0This *only* works for template functions or templates that ca=
n be reduced to template functions.<br>
<br>
So for example:<br>
<br>
T foo(T)(T t) {return t;}<br>
<br>
you can call this function via:<br>
<br>
foo(1);<br>
<br>
And T will implicitly be assigned int.<br>
<br>
But since your getSquares function takes no parameters, IFTI cannot be used=
. =C2=A0Note that the return type does NOT play a role in IFTI.<br>
<br>
However, you can still use getSquares, just specify the template parameter =
explicitly:<br>
<br>
auto sq =3D getSquares!int();<br>
<br>
Another option is to give a default value for T:<br>
<br>
T getSquares(T =3D int)() {...}<br>
<br>
-Steve<br>
</blockquote></div><br><div>This all makes sense. =C2=A0Thanks for the comp=
rehensive explanation. :)</div>
--90e6ba1ef668a82b8704a791917a--