More range woes: std.array.save is invalid

H. S. Teoh hsteoh at quickfur.ath.cx
Thu Dec 20 09:39:21 PST 2012


On Thu, Dec 20, 2012 at 05:30:39PM +0100, monarch_dodra wrote:
> 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.
[...]
> 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.

You're right, if joiner only iterates through .save'd copies of the
subranges, then there will be no problem. Any external modifications is
not our responsibility, because as long as you only iterate over the
joined range (without mutation), it will not cause unexpected
modifications of the original range.


T

-- 
One reason that few people are aware there are programs running the internet is that they never crash in any significant way: the free software underlying the internet is reliable to the point of invisibility. -- Glyn Moody, from the article "Giving it all away"


More information about the Digitalmars-d mailing list