On Friday, 25 November 2016 at 14:27:13 UTC, Ilya Yaroshenko wrote:
The discussion [2] about Mir Random [1] and Range API become a holy war [2]. I am putting the following example here. It also can be found at GitHub[1].

It's not a holy war, but your code example doesn't really address the key issues to do with the interaction of random number generation and ranges, which are not really much about how you create a reference-type range for RNGs themselves. (Your solution is one of several.)

What would convince me of the merits of your approach is an implementation of `RandomSample` (as in, the range that extracts a subset of n elements out of the first N elements of an input range, with equal probability of selecting any particular element) that deals with the following challenges:

* its own internal state (or at least, those parts of it that correspond to state underlying the pseudo-random process, which is NOT limited to the RNG state) is not at risk of being copied by value;

* it's possible to generate multiple `RandomSample` instances deep in the inner loop of a program, without creating slow-down related to memory allocation (this was the reason I abandoned a class-based approach);

* it's easy to fit the `RandomSample` implementation into a range chain.

The last point doesn't have to be quite as simple as the sort of thing you can do currently, such as:

    iota(100).randomSample(10, rng).filter!(a => a > 50).writeln;

Ideally it would be possible to create a function that creates that kind of range chain and returns it, as in:

    auto myMagicRange(RNG)(size_t n, size_t m, ref RNG rng)
    {
        assert(n < m);

        return iota(m).randomSample(n, rng).filter!(a => a > n/2);
    }

    // Now output 10,000 unique filtered samples ...
    foreach (_; 0 .. 10_000)
    {
        myMagicRange(10, 100, rng).writeln;
    }

Reply via email to