Re: Can’t use UFCS to create InputRange?

2020-04-29 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 29 April 2020 at 12:23:11 UTC, Simen Kjærås wrote:
Of course, nothing stops us from defining our own front, 
popFront and friends that combine the two approaches above:



[...]


We could conceivably add these to std.range.primitives 
(probably adding some constraints first), and suddenly UFCS 
ranges are possible! (I am as of yet not convinced that we 
should, though)


--
  Simen


This is basically what C++ calls "argument-dependent lookup." 
Discussion about adding this sort of thing to D has come up 
before on the forums [1], and iirc Walter has generally been 
opposed to it. If it were to be added as a library feature, it 
would probably have to be opt-in.


[1] 
https://forum.dlang.org/post/mailman.123.1472818535.2965.digitalmar...@puremagic.com


Re: Can’t use UFCS to create InputRange?

2020-04-29 Thread Simen Kjærås via Digitalmars-d-learn

On Wednesday, 29 April 2020 at 09:16:58 UTC, user1234 wrote:
The static checker doesn't see your free funcs because to do so 
it would have to import the whole module. (is it possible to do 
that ? no idea.)


Of course it's possible! :) We can find the context of R (in this 
case, the module) with __traits(parent), and import that:


mixin("import "~__traits(parent, R).stringof["module 
".length..$]~";");


However, doing that in isInputRange doesn't help much. First, all 
other range functions would have to do it, and second, just 
importing into function scope doesn't enable UFCS lookup.



Also your signature for the primitives are quite unusual (i.e 
not idiomatic). Usually they dont take param. Usually we pass a 
type that contains the member funcs matching to IsIntputRange.


You can see a good counterexample to this in 
https://dlang.org/library/std/range/primitives/pop_front.html, 
which defines popFront for regular arrays. However, that is the 
one and only counterexample I know of.


Of course, nothing stops us from defining our own front, popFront 
and friends that combine the two approaches above:



template front(R) {
auto front(R r) {
return __traits(getMember, __traits(parent, R), 
"front")(r);

}
}
template popFront(R) {
auto popFront(R r) {
return __traits(getMember, __traits(parent, R), 
"popFront")(r);

}
}
template empty(R) {
auto empty(R r) {
return __traits(getMember, __traits(parent, R), 
"empty")(r);

}
}

We could conceivably add these to std.range.primitives (probably 
adding some constraints first), and suddenly UFCS ranges are 
possible! (I am as of yet not convinced that we should, though)


--
  Simen


Re: Can’t use UFCS to create InputRange?

2020-04-29 Thread user1234 via Digitalmars-d-learn

On Wednesday, 29 April 2020 at 08:34:53 UTC, Ogi wrote:

struct R {}
int front(R r) { return 42; }
void popFront(R r) {}
bool empty(R r) { return false; }

void main() {
import std.range.primitives : isInputRange;
static assert(isInputRange!R);
}


Error: static assert:  `isInputRange!(R)` is false


Whats really weird is that if I replace isInputRange with its 
definition from std.range.primitives, it returns true:


import std;

struct R {}
int front(R r) { return 42; }
void popFront(R r) {}
bool empty(R r) { return false; }

void main() {
static assert(is(typeof(R.init) == R)
&& is(ReturnType!((R r) => r.empty) == bool)
&& is(typeof((return ref R r) => r.front))
&& !is(ReturnType!((R r) => r.front) == void)
&& is(typeof((R r) => r.popFront)));
}
This compiles.

What’s going on here?


The static checker doesn't see your free funcs because to do so 
it would have to import the whole module. (is it possible to do 
that ? no idea.)
Also your signature for the primitives are quite unusual (i.e not 
idiomatic). Usually they dont take param. Usually we pass a type 
that contains the member funcs matching to IsIntputRange.


Re: Can’t use UFCS to create InputRange?

2020-04-29 Thread Simen Kjærås via Digitalmars-d-learn

On Wednesday, 29 April 2020 at 08:34:53 UTC, Ogi wrote:

struct R {}
int front(R r) { return 42; }
void popFront(R r) {}
bool empty(R r) { return false; }

void main() {
import std.range.primitives : isInputRange;
static assert(isInputRange!R);
}


Error: static assert:  `isInputRange!(R)` is false


What’s going on here?



The template IsInputRange is in the std.range.primitives module, 
and thus can't see the front, popFront and empty definitions in 
your module.


--
  Simen


Can’t use UFCS to create InputRange?

2020-04-29 Thread Ogi via Digitalmars-d-learn

struct R {}
int front(R r) { return 42; }
void popFront(R r) {}
bool empty(R r) { return false; }

void main() {
import std.range.primitives : isInputRange;
static assert(isInputRange!R);
}


Error: static assert:  `isInputRange!(R)` is false


Whats really weird is that if I replace isInputRange with its 
definition from std.range.primitives, it returns true:


import std;

struct R {}
int front(R r) { return 42; }
void popFront(R r) {}
bool empty(R r) { return false; }

void main() {
static assert(is(typeof(R.init) == R)
&& is(ReturnType!((R r) => r.empty) == bool)
&& is(typeof((return ref R r) => r.front))
&& !is(ReturnType!((R r) => r.front) == void)
&& is(typeof((R r) => r.popFront)));
}
This compiles.

What’s going on here?