Generality creep

Timon Gehr timon.gehr at gmx.ch
Mon Apr 1 21:23:11 UTC 2019


On 19.03.19 03:52, Andrei Alexandrescu wrote:
> 
> Turns out the second clause fails. That takes us to the definition of 
> empty in the same module:
> 
> @property bool empty(T)(auto ref scope const(T) a)
> if (is(typeof(a.length) : size_t))
> {
>      return !a.length;
> }
> ...

Why should length be required to be `const` when almost everything 
that's `const` is not even a range?

> The intent is fairly clear - if a range defines empty as a size_t 
> (somewhat oddly relaxed to "convertible to size_t"), then empty can be 
> nicely defined in terms of length. Cool. But empty doesn't work with 
> TestAliasedString due to an overlooked matter: the "const". A mutable 
> TestAliasedString converts to a string, but a const or immutable 
> TestAliasedString does NOT convert to a const string! So this fixes that 
> matter:
> 
>      struct TestAliasedString
>      {
>          string get() @safe @nogc pure nothrow { return _s; }
>          const(string) get() @safe @nogc pure nothrow const { return _s; }
>          alias get this;
>          @disable this(this);
>          string _s;
>      }
> 

Reasoning from first principles, the right fix is actually to allow 
non-const length.

> That makes empty() work, but also raises a nagging question: what was 
> the relationship of TestAliasedString to string before this change? 
> Surely that wasn't subtyping. (My response would be: "Odd.") And why was 
> Phobos under the obligation to cater for such a type and its tenuous 
> relationship to a range?

The problem isn't `alias this`. It's `const`. The following type does 
not pass isInputRange either:

struct ApparentlyNotARange{
     size_t k=10;
     int front(){ return 0; }
     void popFront(){ --k; }
     @property size_t length(){ return k; }
}

While this does:

struct ApparentlyNotARange{
     size_t k=10;
     int front(){ return 0; }
     void popFront(){ --k; }
     @property size_t length()const{ return k; }
}

The reason why Phobos ought to be under the obligation to cater for such 
a type is because failure to do so is an artificial limitation. It works 
by default, but someone went out of their way to make sure it does not 
work if `length` is not annotated `const` (or `@property`). This is 
particularly strange because there is no such thing as a const range.


More information about the Digitalmars-d mailing list