A couple of weeks ago on the next/shift convenience wrapper
discussion [1], there was a nice discussion about transient
ranges. It didn't come to a conclusion, so let's revie it. I just
cite the best three quotes from the thread as a summary:
jmdavis:
The reality of the matter is that ranges with a transient front
tend to break if you do much more than use foreach on them.
They don't even work with std.array.array
schveiguy:
There is an implicit expectation that if you assign the front
of a range to something, it's going to last forever, because
many ranges do actually behave that way. But the range contract
does not guarantee that, it just happens to work.
quickfur:
isTransient can only be implemented if the range implementor
defines its value. There is no way to know whether a range is
transient or not just by looking at its type and the signatures
of front, popFront, etc.. Having said that, though, since
transient ranges are generally the exception rather than the
norm, we could adopt a convention that transient ranges declare
themselves thus by defining a .transient enum member or
something like that, and have isTransient return false if a
range doesn't have such a member.
On a related note, there are a good number of Phobos algorithms
that do not work on transient ranges at all, because
internally they (blindly) assume that assigning the value of
.front to a local variable will retain its original value after
popFront is called. I've fixed a couple of places where this
happens, but I'm almost certain many other places haven't been
fixed yet, and in some cases, cannot be fixed without
restricting the algorithms to forward ranges only rather than
input ranges. Some things simply cannot be implemented without
copying .front somehow, and the only way to do this reliably
with the current API is to require forward ranges and use save
to keep track of the previous position of the range.
So what about the convention to explicitely declare a
`.transient` enum member on a range, if the front element value
can change?
[1] https://github.com/dlang/phobos/pull/4010