More range woes: std.array.save is invalid

monarch_dodra monarchdodra at gmail.com
Thu Dec 20 08:30:39 PST 2012


On Thursday, 20 December 2012 at 16:04:43 UTC, H. S. Teoh wrote:
> On Thu, Dec 20, 2012 at 04:47:10PM +0100, monarch_dodra wrote:
> [...]
>> Why is that?
>
> Because the definition of .save only requires that the state of 
> the
> outer range is saved. Nothing is guaranteed about the state of 
> the inner
> ranges.
>
>
>> If the wrapper is *designed* as being a RoR, then the 
>> "elements" of
>> the range are defined as being part of the iteration scheme.  
>> Once you
>> have defined it that way, you can have the wrapper save the 
>> top Range,
>> as well as each sub-range individually, and then the wrapper is
>> Forward... No?
>
> In *theory*, yes, you can do this. But currently, it's not 
> possible to
> do this generically, because .save has to return the same type 
> as the
> outer range. The outer range's .save method does NOT call .save 
> on the
> inner ranges (e.g., an array of forward ranges: std.array.save 
> simply
> returns a shallow copy of the original array). So the inner 
> ranges will
> be invalidated by iterating either the .save'd range, or the 
> original
> range.
>
> You have to return an outer range in which all of its elements 
> have been
> replaced with .save'd copies. But there is no method in the 
> outer range
> that does this, so there is no way to do this in generic code.
>
> *If* .save is allowed to return a different type, then yes, you 
> can
> return a wrapper of the outer range that lets you iterate 
> through
> .save'd copies of the inner ranges. But AFAIK this isn't 
> allowed by the
> current definition of .save.
>
>
> T

Yeah..., I think I get it now. Thanks for insisting.

While you _can_ save the outer range, if you try to replace the 
individual elements of the saved range with saved copies, at the 
end of the day, both your outer ranges will still reference the 
same ranges, saved or not. Ok. Now we can move forward.

One of the solutions I see would be that the RoR wrapper (we're 
talking about Joiner, right?), never mutate the elements of the 
RoR directly, but first store a *saved* copy of the element into 
a _current.

This way, you only need to save the *outer* range, but not *ALL* 
of the inner ranges individually. This is good because it keeps 
things in check performance wise.

I commented on your fix to joiner:
https://github.com/D-Programming-Language/phobos/pull/987/files#r2478956
This may solve the problem actually.


More information about the Digitalmars-d mailing list