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

Paul Backus snarwin at gmail.com
Sun Jun 28 16:37:23 UTC 2020


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

For *some* forward ranges, it will be possible to implement 
next() as well, in which case those ranges will be capable of 
functioning as both input ranges and forward ranges. I don't see 
anything wrong with that.

>> 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():

     // Just enough for the example to compile
     struct Optional(T)
     {
         bool empty;
         T value;
     }

     Optional!T some(T)(T value)
     {
         return Optional!T(false, value);
     }

     Optional!T no(T)()
     {
         return Optional!T(true, T.init);
     }

     auto fdByChar(int fd)
     {
         import core.sys.posix.unistd;

         static struct Result
         {
             private int fd;

             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");
             }
         }

         return Result(fd);
     }

And here's the usage:

     void each(alias fun, Range)(Range range)
     {
         for (auto e = range.next; !e.empty; e = range.next)
             fun(e.value);
     }

     void main()
     {
         import std.stdio;
         immutable stdinByChar = fdByChar(0);
         stdinByChar.each!writeln;
     }

Once again, `stdinByChar` is an input range, and it is immutable. 
QED.


More information about the Digitalmars-d mailing list