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

Reply via email to