Rand crate brainstorming (minimal API in std?)


#1

I think there are two important goals around the rand crate: get it to 1.0 and possibly get a minimal version of its API included in std. @aturon, @alexcrichton and I talked about this and here are some of our thoughts. Is anyone interested in leading the charge here? For reference, @huon has a pretty big refactor here on the next branch: https://github.com/huonw/rand/tree/next

Some big picture thoughts:

  • It would be nice if distribution based generation worked the same way as simple/uniform generation. I think the current rand crate doesn’t do that, but @huon’s branch does.
  • It should be pretty ergonomic to do operations like “just give me a random value.”

Some specific API thoughts:

trait Rand<Dist> {
    fn rand(dist: Dist) -> Self {
        Self::with_rng(dist, &mut thread_rng())
    }

    fn with_rng<R: Rng>(dist: Dist, rng: &mut R) -> Self;
}

This is nice because then you can use ranges to specify distributions, i.e., impl Rand<ops::Range> for i32, which let’s you do i32::rand(15..37). i32::rand(..) is a touch weird though.

One issue is that the @huon’s current refactor has an extra indirection in the types, where the Rand trait looks like:

pub trait Rand<Distribution>: Sized {
    type Stream: RandStream<Self>;

    fn rand(dist: Distribution) -> Self::Stream;
}

pub trait RandStream<Output> {
    fn next<R: Rng>(&self, rng: &mut R) -> Output;
}

and some blanket impls:

impl<'a, T, D: RandStream<T>> RandStream<T> for &'a D {
    fn next<R: Rng>(&self, rng: &mut R) -> T {
        (**self).next(rng)
    }
}

impl<T, D: RandStream<T>> Rand<D> for T {
    type Stream = D;
    fn rand(d: D) -> D { d }
}

It would be nice to simplify things and get rid of RandStream, but I ran into problems. (I think Generator might require it.)


#2

I haven’t done a lot of work with rand, but I do use it in the book. The “give me a random number” case ends up taking all this stuff:

extern crate rand;

use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);
}

It’d be nice to have some kind of convenience function for “just do the right thing and give me some numbers in this range” rather than needing to use a trait.


Brson's "someday" list
#3

There’s already rand::random() which uses thread_rng().gen(). I guess you want something similar like rand::random_range(low, high).


#4

For the distributions it would be great to also provide the probability density function, the cumulative distribution function and the quantile function. They are needed frequently when doing statistics.

This is what R is doing (see here).