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.

Reply via email to