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.)