wrong isInputRange design

rumbu via Digitalmars-d digitalmars-d at puremagic.com
Sun Dec 4 05:37:35 PST 2016


On Sunday, 4 December 2016 at 11:50:08 UTC, Mike Parker wrote:
> On Sunday, 4 December 2016 at 11:18:56 UTC, rumbu wrote:
>
>
>>
>> Of course, the previous code will compile if we change the 
>> imports:
>> import std.range.primitives: isInputRange, front, popFront, 
>> empty;
>>
>> But that just prove the bad design of isInputRange which 
>> cannot be used all alone without the rest of array UFCSs 
>> imported.
>
> isInputRange can be used alone just fine. But you aren't using 
> it alone.

  I'm using it all alone:

auto first(R)(R range) if (isInputRange!R)
{
   return range.front;
   //compile time error when calling first!string
}

auto first(C)(const(C)[] str)
{
    return str[0];
    //never called;
}

first(someString);

> You're using it together with the range primitives for arrays, 
> but you are explicitly excluding them from the import by only 
> selectively importing isInputRange. The import is working 
> exactly as advertised. What is it about this case that makes 
> you think it should behave differently?

Advertising from the docs says this: "An input range must define 
the primitives empty, popFront, and front." In my module context, 
I didn't define any of them, isInputRange!string must return 
false, because string is not a range, I repeat - *in my module 
context*. There is nowhere in the documentation where arrays are 
advertised as  ranges by default.

If I copy the isInputRange definition in my module, it will 
clearly return false:

import std.range.primitives: isInputRange;
template isInputRange2(R)
{
     enum bool isInputRange2 = is(typeof(
     (inout int = 0)
     {
         R r = R.init;     // can define a range object
         if (r.empty) {}   // can test for empty
         r.popFront();     // can invoke popFront()
         auto h = r.front; // can get the front of the range
     }));
}


static assert(isInputRange!string); //wrong!
static assert(!isInputRange2!string); //correct!

I think that the array range UFCSs must be moved out from the 
std.range.primitives and let the library user to decide if there 
is a need for range semantics applied to all arrays.

Otherwise, as long as you want array specializations for your 
functions, you must decorate all the range specializations with 
(isInputRange!T && !isArray!T). And you are compelled to use 
"f(T)(T t) if isArray!T" for all your array specializations 
instead of "f(T)(T[] x)".









More information about the Digitalmars-d mailing list