More tricky range semantics
Joseph Rushton Wakeling via Digitalmars-d
digitalmars-d at puremagic.com
Fri Jan 16 08:12:22 PST 2015
On Friday, 16 January 2015 at 14:59:10 UTC, Dicebot wrote:
> To specify : the way I see it you either want PRNG to be a
> forward range and that fits with value semantics. Or you want
> reference semantics and it naturally becomes input range.
Here's the problem with value semantics. This is a real problem
with actual Phobos code right now.
////////////////////////////////////////////////////
import std.random, std.range, std.stdio;
void main()
{
// Create RNG instance with unpredictable seed
auto rng = Random(unpredictableSeed);
// Generate sample of 3 numbers from sequence
// 0, 1, ..., 9 using rng as source of randomness
// and write to console
iota(0, 10).randomSample(3, rng).writeln;
// Do again. We'd expect a different result
// but actually we get just the same
iota(0, 10).randomSample(3, rng).writeln;
}
////////////////////////////////////////////////////
Note that because randomSample generated a wrapper range
(RandomSample), we can't simply pass the RNG by ref. It's copied
(and because RNGs are currently value types, it's copied by
value).
Note also that the above is a problem whether or not Random is a
forward or input range.
What's needed here is for the source of randomness to be updated
whenever it's used, so that you don't get unintended correlations
like this. Reference types give this, but it shouldn't be
necessary to interfere with the forward-range status of the RNG,
which depends entirely on whether it's a deterministic pseudo-RNG
or not.
Conversely, suppose that we have some function that takes a
forward range as input and uses the ability to repeat the
sequence. Here's a naive example:
void foo (FRange) (FRange range)
if (isForwardRange!FRange)
{
foreach (i; 0 .. 10)
{
// silly example :-P
auto r = range.save;
r.take(10).writeln;
}
}
This is a problematic design if FRange is a reference type,
because (by design) if the values in it are used, they should be
consumed. So e.g. if you were passing a reference-type RNG to a
function that does this, you'd like to guarantee that (i) the
function is able to use the ability to repeat the sequence, but
(ii) consumes from the original exactly once.
If you don't get that, you will wind up with unintended
correlations in your use of random numbers.
More information about the Digitalmars-d
mailing list