More tricky range semantics

Joseph Rushton Wakeling via Digitalmars-d digitalmars-d at puremagic.com
Thu Jan 15 13:41:04 PST 2015


On 15/01/15 21:53, H. S. Teoh via Digitalmars-d wrote:
> a) At least as things currently stand, passing (wrapper) ranges around
> may exhibit "undefined" behaviour, like the above. Passing a range to a
> function may invalidate it unless you use .save.  Therefore, one should
> *always* use .save. (If we had passed wrapper.save to equal() instead,
> this problem would not have happened.) This applies even if the wrapper
> range is a by-value type. Or should we say, *especially* when it's a
> by-value type?
>
> b) One may argue that WrapperRange ought to .save the underlying range
> in its postblit... but what if the only thing we wanted to do was to
> call equal() on wrapper and nothing else? In that case, we'd be
> incurring needless overhead of .save'ing the range when we didn't care
> whether it got consumed.
>
> c) This issue is already latent in almost *all* Phobos algorithms.  We
> only haven't discovered it yet because most people just use arrays for
> ranges. But all it takes is for somebody to start using
> std.range.inputRangeObject (and there are cases where this is
> necessary), and this problem will surface.  Anytime you mix by-value and
> by-reference ranges, be ready for problems of this sort to arise.
>
> Yep, range semantics just got even trickier. (And we thought transient
> ranges were bad...)

Yes, there are a lot of complications here.  You may recall the issues discussed 
numerous times about std.random, and in particular the horrendous problems of 
value-type RNGs?

Switching to reference types still leaves some nasty possibilities.  For 
example, suppose you have an RNG that _is_ a reference-type range.  Now you pass 
it to a function that needs to re-use the range it's given as input, multiple 
times -- so it calls .save on the range it is given and only uses saved copies.

That function produces its output "correctly" with its .save'd range, but now 
your original RNG is unchanged, because the values were extracted from a saved 
copy.  So, the next time you use that RNG, the values it produces will be 
correlated with the values used in this function.

Ouch!


More information about the Digitalmars-d mailing list