Using map result type

mipri mipri at minimaltype.com
Sun Dec 8 01:43:43 UTC 2019


On Sunday, 8 December 2019 at 01:10:21 UTC, AA wrote:
> I'd like to accept the return type of map. From some previous
> questions that I should accept a template?

In general this is what you want to do with any kind of range
code, because you're not working with definite types, but with
types that have certain properties. And an advantage of this is
that you can decide to do more or less efficient things at
compile time based on additional properties of the types you're
working with. Just open up phobos and look for 'static if':

https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L3858

So if you you give minPos an array, it'll just foreach() over
the array and return a slice. In which case minPos is exactly
as efficient as the code you would've written by hand instead
of using minPos, because it expands to that same code.

And if you give minPos something else, it'll still work.

> So for something like:
>
> ```
> void mapAccepter(Range)(Range r)
> {
>     import std.array : array;
>     import std.stdio : writeln;
>
>     auto collected = r.array;
>     writeln(collected);
> }
>
> void main()
> {
>     import std.algorithm.iteration : map;
>
>     int[] nums = [1, 2, 3];
>     auto evenness = map!(n => n % 2 == 0)(nums);
>     mapAccepter(evenness);
> }
> ```

> 1) Is there any way I can make `mapAccepter` not a templated
> function?

Not really. Even if you try to use typeof() to get the
(internal) type that std.alogorithm.map returns, you'll run
into errors like

Error: function x253.mapAccepter(MapResult!(__lambda5, int[]) r) 
is not callable using argument types (MapResult!(__lambda1, 
int[]))

when you try to use it.

> 2) Is there any way if I need to make `mapAccepter` templated
> to constrain Range to be a range of booleans.

Certainly. Static reflection's what this kind of generic code
is all about. See all the constraints in the std.algorithm pages
in the library documentation?  Just look at this one, randomly
picked:
https://dlang.org/phobos/std_algorithm_searching.html#.endsWith

   if (isBidirectionalRange!Range
       && (Needles.length > 1)
       && is(typeof(.endsWith!pred(doesThisEnd, 
withOneOfThese[0])) : bool)
       && is(typeof(.endsWith!pred(doesThisEnd, 
withOneOfThese[1..$])) : uint));

So for your code:

   void mapAccepter(Range)(Range r)
       if (is(ElementType!Range == bool))
   {
       import std.array : array;
       import std.stdio : writeln;

       auto collected = r.array;
       writeln(collected);
   }

Or if you do this often, maybe something like this would do:

   enum RangeOfBools(T) = is(ElementType!T == bool) && 
isInputRange!T;

   void mapAccepter(Range)(Range r) if (RangeOfBools!Range)
   {
       import std.array : array;
       import std.stdio : writeln;

       auto collected = r.array;
       writeln(collected);
   }



More information about the Digitalmars-d-learn mailing list