More range woes: std.array.save is invalid

H. S. Teoh hsteoh at quickfur.ath.cx
Thu Dec 20 08:03:04 PST 2012


On Thu, Dec 20, 2012 at 04:47:10PM +0100, monarch_dodra wrote:
> On Thursday, 20 December 2012 at 15:25:27 UTC, H. S. Teoh wrote:
> >On Thu, Dec 20, 2012 at 12:08:24AM -0800, Jonathan M Davis wrote:
> >>On Wednesday, December 19, 2012 23:44:12 H. S. Teoh wrote:
> >>> Yes, which means many current algorithms that take a range of
> >>> ranges and returns a wrapper range are wrong, because they assume
> >>> that the wrapper range can be a forward range when both the
> >>> container and the subranges are forward ranges, but this is not a
> >>> sufficient condition in the general case.
> >>
> >>Then they have bugs in their implementation which need to be fixed.
> >>There's nothing wrong with std.array.save. It's doing the right
> >>thing.
> >[...]
> >
> >OK, so the subject line is misleading.
> >
> >But the bigger issue is that wrappers of forward ranges of forward
> >ranges can only be input ranges, in spite of the fact that, in
> >theory, you can save each component of the given range of ranges.
[...]
> 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

-- 
Why waste time learning, when ignorance is instantaneous? -- Hobbes, from Calvin & Hobbes


More information about the Digitalmars-d mailing list