Forward ranges in Phobos v2

H. S. Teoh hsteoh at quickfur.ath.cx
Tue Nov 9 23:08:13 UTC 2021


On Fri, Nov 05, 2021 at 11:43:01AM +0000, Atila Neves via Digitalmars-d wrote:
> On Thursday, 4 November 2021 at 23:30:05 UTC, H. S. Teoh wrote:
[...]
> > Yeah, we need to get rid of useless genericity, and also exactly
> > what is expected of range operations should be stated clearly and
> > unambiguously in the API docs.  The current range API suffers from
> > insufficient clarity, so many such cases went "under the radar" and
> > inevitably ended up being implemented when some kind soul decided
> > that it would be nice to support this or that niche case.
> 
> Sometimes genericity is a good thing. Take C++, where range for was
> originally specified in C++11 such that the begin and end iterators
> had to be the same type, which on the face it seems to makes sense.
> But then that was found out to be overly constraining, and to be able
> to add ranges to C++17 they had to change the definition of a range
> for loop so that end only had to be comparable to begin and could be a
> different type.

Genericity is definitely a good thing -- when it doesn't lead to the
slippery slope of ever-more-complicated convolutions in the code as a
result of trying to cater to every unnatural use case.  The whole point
of the range abstraction is to *simplify* code; if simplicity and
clarity of code is compromised because of genericity, then we have
failed.


[...]
> > Yeah, .empty should return bool, and only bool.  Not
> > immutable(bool), not something that alias this to bool, none of that
> > sort.
> > 
> > Also, the spec should specify precisely whether .empty must be a
> > function (and whether it should be a member function, a free
> > function, or both), or it's allowed to be a member variable.
> 
> Similarly to what I said above, I don't think the spec should do this
> at all. Plasticity is what D is good at, and leaving it to
> "range.empty is a bool" is, IMHO, far better. I *love* not using
> parens for functions with no args and being able to use a
> function/variable/enum, then being able to change that and not have to
> touch the rest of the code at all.

I disagree. The spec *should* explicitly state what .empty (or any other
range method/identifier) is allowed to be.  If you want more genericity,
simply have the spec say ".empty may be either a method or a member
field".

This may seem trivial, but it's necessary to prevent things like some
Phobos code assuming that .empty is always a method, and then it fails
when somebody passes in a range that has a field instead.  Also, on the
user-facing side, it prevents spurious bug reports like "how come my
custom-made range with non-copyable .empty masqueraded from a nested
struct via alias this doesn't pass isInputRange?", which then prompts
some well-meaning soul to implement support for this obscure case,
thereby adding all kinds of weird fluff to Phobos that really don't
belong there.

We want to be able to say to such bug reports, "the spec says .empty can
only be method or a bool field, sorry we don't support stuff where
.empty is a non-copyable wrapper object that uses alias this to
implicitly convert to a value wrapper with an .opCast!bool that returns
an immutable(bool) which can then be value-copied onto a bool".

Andrei has said many times that these kinds of obscure cases don't
belong to Phobos. If some user wants static arrays to work with ranges,
then just write `[]` and be done with it, instead of adding yet another
useless feature to Phobos (which inevitably will cause some unexpected
poor interaction with another obscure case, and we're stuck in the
endless churn of accreting features in Phobos that make it harder to
maintain yet does not actually make any progress in improving D code).
If somebody wants .empty to be a wrapper struct that uses alias this and
.opCast!bool to return an immutable(bool), just have them write a
wrapper that uses a function .empty to return a bool.

The fact that user code ended up in such a tangled mess is a sign that
something is wrong on *their* side; we should not be promoting bad code
practices by supporting such monstrosities in Phobos; we should instead
be triggering a compile error so that the user cleans up his act and
writes better code.


T

-- 
Insanity is doing the same thing over and over again and expecting different results.


More information about the Digitalmars-d mailing list