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

Jonathan M Davis newsgroup.d at jmdavisprog.com
Tue Jun 23 06:13:45 UTC 2020


On Monday, June 22, 2020 11:19:35 PM MDT Andrei Alexandrescu via Digitalmars-d 
wrote:
> On 6/22/20 6:54 PM, Jon Degenhardt wrote:
> > On Monday, 22 June 2020 at 02:52:57 UTC, Andrei Alexandrescu wrote:
> >> On 6/21/20 10:47 AM, Andrei Alexandrescu wrote:
> >> One more thing before I forget - we should drop classes that are
> >> ranges. They add too much complication. The functionality would still
> >> be present by wrapping a polymorphic implementation in a struct.
> >
> > I have used class-based ranges quite a bit to implement ranges with
> > reference semantics. Classes are very convenient for this because the
> > implementation is structurally very similar to a struct based
> > implementation. Typically, replace 'struct' with 'final class' and
> > modify a helper function constructing the range to use 'new'. It's
> > amazingly easy.
> >
> > So - What aspects of class-based ranges is it valuable to drop?
> > Polymorphism/inheritance? Reference semantics? Both?
> >
> > I haven't found a need for polymorphism in these ranges, just reference
> > semantics. I realize that the Phobos experience is the opposite, that
> > reference ranges are rarely used. Could be that my design choices could
> > be modified to eliminate reference ranges. Could also be that approaches
> > needed in general libraries are not always necessary in code targeting
> > specific applications. Not trying to make hard claims about this. Just
> > pointing out where I've found value.
>
> Problem is they're cumbersome to use - you need to remember to call
> save() in key places, and if you forget the compiler will be mum about
> it. If we do away with class ranges, save() can be eliminated in favor
> of the copy ctor.
>
> I assume a wrapper that does define reference semantics where needed
> would not be difficult to write.

Except that if a forward range has reference semantics, then copying it is
not equivalent to calling save. If we get rid of save in favor of using copy
constructors, then we're requiring that all forward ranges have the same
copying semantics and that that be that copying a forward range results in a
copy that can be independently iterated over. Some internals could use
references to be sure, but we get rid of the ability to have forward ranges
which are actually reference types. They have to have the copying semantics
of value types with regards to at least their iteration state.

Now, one of the problems that we have with ranges as things stand is that
the semantics of copying a range are unspecified and can vary wildly
depending on the range's type, meaning that if a range is copied, you can't
ever use it again (at least in generic code), because the state of the
original is unknown after mutating the copy. It could be unchanged, be in
the same state as the copy, or even be in an invalid state due to the copy
mutating part of its state but not all of it. So, overall, having forward
ranges require that copying do what save now does would be a considerable
improvement with regards to cleaning up the copying semantics.

Of course, that still leaves the problem of basic input ranges, since they
can't have value semantics when copying (if they could, then they could be
forward ranges). Pretty much by definition, basic input ranges are either
reference types or pseudo-reference types (or the programmer was just lazy
and didn't implement save). So, unfortunately, generic code that operates on
both basic input ranges and forward ranges can't ever have guaranteed
copying semantics. I think that we should try to nail down the copying
semantics for ranges as much as we can though. Similarly, we should probably
place requirements on the semantics of assigning to a range. That would
almost certainly kill off RefRange, but IMHO, RefRange was a mistake anyway.

- Jonathan M Davis





More information about the Digitalmars-d mailing list