Transience of .front in input vs. forward ranges
Jonathan M Davis
jmdavisProg at gmx.com
Sun Nov 4 19:08:28 PST 2012
On Sunday, November 04, 2012 21:49:58 Dmitry Olshansky wrote:
> I was mostly going by:
> > The simpler way would be to simply state that input ranges can't
>
> guarantee the persistence of .front after calling .popFront.
>
> and
>
> >The algorithms that need to worry about .front's transience are only
>
> the ones that work with input ranges (as opposed to forward ranges or
> stronger).
>
> And conclude that applying this simple rule to std.array.array* means it
> has to assume non-transient elements and somehow copy/dup'em. Problem is
> we don't have generic function to make 100% guaranteed unaliased copy
> (it could omit doing any work on non-aliased objects).
>
> Also that it misses forward ranges that have aliased .front, assuming
> they are non-transient.
The reality is that in the general case, you can't know for certain whether
the result of front is transient or not. In some cases, you know, because the
type is clearly immutable or a value type. In others (e.g. char[]), you can't
know. A particularly annoying one though is classes, because they're almost
never going to be immutable, so in almost all cases, if input ranges can have
transient fronts and the range's element types is a class, then you have to
assume that its front is transient. And I'm not sure whether it's possible to
determine whether a struct is a value type or a reference type or not. The
mutable indirections bit probably makes it so that you can determine for sure
that some structs are value types, but you can't be certain for some of them
whether they're a reference type or value type without examining the postblit
constructor.
So, what it ends up coming down to if we accept that input ranges can have
transient fronts is that algorithms then either have to require forward ranges
in the case where they need to keep the result of front around, or we need a
template of some kind which can determine in at least some cases that front in
not transient (but it's going to have to say that front is transient in many
cases where it isn't), and such algorithms will have to use that trait when
dealing with input ranges.
The big problem though is std.array.array. Based on the functions that an
input range has, all it needs is an input range, but it'll never work with a
transient front. So, what is likely one of the most heavily used range-based
functions can't work with input ranges. This is a big problem, and fixing it
_will_ break code. Because either, we need to create a hasTransientFront
template or make std.array.array require at least a forward range, which will
make dealing with input ranges that much worse.
Still, as much as I hate the idea of permitting transient fronts, I'd rather
have it be part of input ranges and be able to assume that other range types
have non-transient fronts than create isTransient. Ranges are already overly
complicated as it is. Regardless, if we decide that input ranges can have
transient fronts, then we need to make that very clear, which clearly hasn't
been the case, because only Andrei thought that the transience of front had
anything to do with the definition of an input range.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list