std.v2020.algorithm etc[ WAS: Is run.d going to be expand for runtime and the phobos library?]

Stanislav Blinov stanislav.blinov at gmail.com
Mon Jun 29 15:40:28 UTC 2020


On Sunday, 28 June 2020 at 16:37:23 UTC, Paul Backus wrote:
> On Sunday, 28 June 2020 at 15:33:48 UTC, Stanislav Blinov wrote:
>> On Sunday, 28 June 2020 at 14:12:39 UTC, Paul Backus wrote:
>>
>>> It sounds like what you are really trying to say here is that 
>>> input ranges and forward ranges should not use the same 
>>> interface, and that input ranges should instead implement 
>>> only `Option!T next()`.
>>
>> Not exactly. A given forward range may also implement such a 
>> `next`. [...] We should differentiate by some other artifact. 
>> I maintain that artifact should be copyability. Or we can keep 
>> the distinction based on the presence of save(), and live 
>> forever with the ambiguous semantics and the "don't use 
>> original after copy unless you know what you're doing" 
>> convention (yuck). Are there even other options besides 
>> accepting UB?
>
> If input ranges are only required to implement next(), then the 
> distinction will be that forward ranges implement head()/tail() 
> and input ranges don't. (In this scenario, head() and tail() 
> will of course be required to return the same result if called 
> multiple times.)

Just as forward ranges may implement `next()`, some input ranges 
may want to be buffered, i.e.:

struct Wrapped
{
     private typeof(src.next()) buf; // Optional!ElementType
     private Input src; // Input is a `next()` input range

     @property bool empty() const { return !buf; }
     T moveFront() { return buf.replace(T.init); }
     void popFront() { buf = src.next; }

     // no front, only moveFront
}

If we put a hard requirement on input ranges to *only* exist with 
the next() interface, this will shut down possible optimizations 
that buffering enables. We can't implement a buffering range in 
terms of the `next()` interface, a staggered fetch + advance is 
required. (next() may overwrite the internals of the buffer 
before client has a chance of reading the value).

>>> My example was a response to the specific claim that "an 
>>> immutable input range cannot exist." Specifically, it was a 
>>> counterexample demonstrating that the claim is false. As I'm 
>>> sure you can see, the claim is still false even if we agree 
>>> to use next() instead of tail() for input ranges, since 
>>> next() is obviously allowed to be impure.
>>
>> I can't see that. I don't see how you're falsifying that claim
>> when in order to implement the range you need mutable state.
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Ok, I'll show you. Here's the same range implemented using 
> next() instead of front() and tail():
>
>             Optional!char next() const
>             {
>                 char c;
>                 ssize_t nread = read(fd, cast(void*) &c, 1);
                                   ^^^^
>
>                 if (nread == 0)
>                     return no!char;
>                 else if (nread == 1)
>                     return some(c);
>                 else
>                     throw new Exception("Error reading file");
>             }
>         }
> Once again, `stdinByChar` is an input range, and it is 
> immutable. QED.

:) Fine. An input range can't exist without mutable state. Is 
that statement more agreeable for you?


More information about the Digitalmars-d mailing list