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)".