Return type of std.algorithm.map

James Fisher jameshfisher at gmail.com
Fri Jul 8 08:06:30 PDT 2011


OK, good replies.  Cool.  So the two places I thought I'd need to use
explicit types are in parameter and return types.  Say, a function returns
the result of map, and another consumes it to print it.  The consuming
function seems to work with templating:

void printSquares(T)(T squares) {
  writeln(squares);
}

void main() {
  int[] start = [1,2,3,4,5];
  auto squares = map!((a) { return a * a; })(start);
  printSquares(squares);
}


However, returning the result of map doesn't seem to work so well with the
same method:

T getSquares(T)() {
  int[] start = [1,2,3,4,5];
  return map!((a) { return a * a; })(start);
}

void main() {
  auto squares = getSquares();
  writeln(squares);
}


Gives the errors:

test.d(11): Error: template test.getSquares(T) does not match any function
template declaration
test.d(11): Error: template test.getSquares(T) cannot deduce template
function from argument types !()()


But this does work with auto return type inference:

auto getSquares() {
  int[] start = [1,2,3,4,5];
  return map!((a) { return a * a; })(start);
}

void main() {
  auto squares = getSquares();
  writeln(squares);
}


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

On Thu, Jul 7, 2011 at 7:31 PM, Steven Schveighoffer <schveiguy at yahoo.com>wrote:

> On Thu, 07 Jul 2011 10:00:48 -0400, James Fisher <jameshfisher at gmail.com>
> wrote:
>
>  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.
>
>
>  it'd
>> be nice to do:
>>
>> import std.algorithm;
>> import std.stdio;
>>
>> void main() {
>>  int[] start = [1,2,3,4,5];
>>  int[] squares = map!((a) { return a * a; })(start);
>>  writeln(squares);
>> }
>>
>>
>> but this gives "Error: cannot implicitly convert expression (map(start))
>> of
>> type Result to int[]".  That opaque type "Result" is weird (not
>> parameterized on "int"?), but OK, let's try that:
>>
>> import std.algorithm;
>> import std.stdio;
>>
>> void main() {
>>  int[] start = [1,2,3,4,5];
>>  Result squares = map!((a) { return a * a; })(start);
>>  writeln(squares);
>> }
>>
>>
>> gives "undefined identifier Result".  Not sure why, but OK.  I can't see
>> examples in the docs of explicit type declarations -- annoyingly they all
>> use "auto".
>>
>
> 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:
>>
>> import std.algorithm;
>> import std.stdio;
>> import std.range;
>>
>> void main() {
>>  int[] start = [1,2,3,4,5];
>>  InputRange!int squares = map!((a) { return a * a; })(start);
>>  writeln(squares);
>> }
>>
>>
>> But the compiler complains "cannot implicitly convert expression
>> (map(start)) of type Result to std.range.InputRange!(int).**InputRange".
>>
>
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20110708/6eaf451e/attachment-0001.html>


More information about the Digitalmars-d-learn mailing list