Using map result type

AA duser at fastmail.com
Tue Dec 10 07:23:56 UTC 2019


On Sunday, 8 December 2019 at 01:43:43 UTC, mipri wrote:
> On Sunday, 8 December 2019 at 01:10:21 UTC, AA wrote:
>> [...]
>
> 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.
>
>> [...]
>
>> [...]
>
> 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.
>
>> [...]
>
> 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);
>   }

Thanks for the detailed reply. So maybe it is just my perspective 
coming from other languages that I was expecting a class i.e. 
having some interface based way of dealing with the return type. 
But I guess isInputRange checks for structural equality rather 
than class and doesn't encode that into any interfaces in std 
library normally?

Would the second solution of declaring a template constraint like 
that be considering strange/out of place in D? e.g. do people 
normally try and declare the template constraints on a function 
or just rely on compile time failure from to instantiate template.


More information about the Digitalmars-d-learn mailing list