On Friday, 27 November 2015 at 10:17:46 UTC, Joseph Rushton
Wakeling wrote:
On Friday, 27 November 2015 at 09:20:23 UTC, Jonathan M Davis
wrote:
Obviously, Andrei will have to answer to know what he meant,
but with regards to ranges, I would consider a reference type
to be one where in
auto copy = range;
doing anything to copy or range does the exact same thing to
the other, because they refer to the exact same state.
Something like save is required to get a separate range where
popping elements from one will not affect the other.
Unfortunately it's a bit more complicated than that, because
it's readily possible to have ranges where
auto copy = range;
... will copy _some_ of the internals by value, and some by
reference -- e.g. a range whose private data includes some
integer values and a dynamic array.
That's not necessarily a problem if the reference-type data
does not influence the range's behaviour (e.g. you're doing
forward iteration over a container accessed by ref), but it's
readily possible to imagine a range design where
auto copy = range;
copy.popFront();
... will affect range's state without updating it to the _same_
state as copy.
Yes. I discussed that in my post, though maybe I wasn't clear
enough. But such a range requires save just as much as a full-on
reference type does, so ultimately it's pretty much in the same
boat as far as save goes. It's also a serious problem for pure
input ranges to such ranges exist, since then even if you can
assume that any range which can implement save does implement
save, you still can't guarantee that an input range is a
reference type, which becomes a serious problem when an input
range is copied. e.g.
foreach(e; range)
{
if(cond)
break;
}
range.popFront();
could be fine if you can guarantee that the range is a reference
type, but if you can't guarantee that (as is currently the case),
then as soon as you use a pure input range with a foreach loop,
you can't use it anymore, because it's copied as part of the
lowering. To get around that, you can use a for loop directly,
but the fact that pure input ranges aren't currently guaranteed
to be reference types definitely makes it harder to write
consistent, correct code with pure input ranges.
As it stands, forward ranges have the same problem, but by
calling save, you can ensure that the copy is separate from the
original and ensure that iterating the original after the loop is
fine (though if you want reference semantics, you would still
have to use a for loop), but pure input ranges don't have a way
to ensure consistency like that other than maybe wrapping the
range in another type which you can guarantee is a reference type.
Regardless, even if we require that pure input ranges be
reference types and that forward ranges be value types (at least
insomuch as copying them results in a separate range with the
same state like with save), we then still have the problem that
pure input ranges and forward ranges have different semantics.
But as long as dynamic arrays are ranges, it's not like we could
force all ranges to be reference types, and that wouldn't be good
for efficiency anyway, since it would almost certainly mean more
heap allocations just so that they can be reference types.
- Jonathan M Davis