range.save
Jonathan M Davis via Digitalmars-d
digitalmars-d at puremagic.com
Fri Nov 27 02:43:26 PST 2015
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
More information about the Digitalmars-d
mailing list