Skip to content

Commit

Permalink
Relax Sized bounds of sample_iter functions and take distr by value
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Apr 17, 2019
1 parent 6614c7c commit 52a9307
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 13 deletions.
35 changes: 30 additions & 5 deletions src/distributions/mod.rs
Expand Up @@ -182,6 +182,12 @@ pub trait Distribution<T> {
/// Create an iterator that generates random values of `T`, using `rng` as
/// the source of randomness.
///
/// Note that this function takes `self` by value. This works since
/// `Distribution<T>` is impl'd for `&D` where `D: Distribution<T>`,
/// however borrowing is not automatic hence `distr.sample_iter(...)` may
/// need to be replaced with `(&distr).sample_iter(...)` to borrow or
/// `(&*distr).sample_iter(...)` to reborrow an existing reference.
///
/// # Example
///
/// ```
Expand All @@ -203,8 +209,8 @@ pub trait Distribution<T> {
/// println!("Not a 6; rolling again!");
/// }
/// ```
fn sample_iter<'a, R>(&'a self, rng: &'a mut R) -> DistIter<'a, Self, R, T>
where Self: Sized, R: Rng
fn sample_iter<'a, R>(self, rng: &'a mut R) -> DistIter<'a, Self, R, T>
where R: Rng + ?Sized, Self: Sized
{
DistIter {
distr: self,
Expand All @@ -229,8 +235,8 @@ impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
///
/// [`sample_iter`]: Distribution::sample_iter
#[derive(Debug)]
pub struct DistIter<'a, D: 'a, R: 'a, T> {
distr: &'a D,
pub struct DistIter<'a, D, R: 'a + ?Sized, T> {
distr: D,
rng: &'a mut R,
phantom: ::core::marker::PhantomData<T>,
}
Expand Down Expand Up @@ -340,7 +346,8 @@ pub struct Standard;

#[cfg(all(test, feature = "std"))]
mod tests {
use super::Distribution;
use ::Rng;
use super::{Distribution, Uniform};

#[test]
fn test_distributions_iter() {
Expand All @@ -350,4 +357,22 @@ mod tests {
let results: Vec<f32> = distr.sample_iter(&mut rng).take(100).collect();
println!("{:?}", results);
}

#[test]
fn test_make_an_iter() {
fn ten_dice_rolls_other_than_five<'a, R: Rng>(rng: &'a mut R) -> impl Iterator<Item = i32> + 'a {
Uniform::new_inclusive(1, 6)
.sample_iter(rng)
.filter(|x| *x != 5)
.take(10)
}

let mut rng = ::test::rng(211);
let mut count = 0;
for val in ten_dice_rolls_other_than_five(&mut rng) {
assert!(val >= 1 && val <= 6 && val != 5);
count += 1;
}
assert_eq!(count, 10);
}
}
14 changes: 6 additions & 8 deletions src/lib.rs
Expand Up @@ -215,26 +215,24 @@ pub trait Rng: RngCore {
/// let mut rng = thread_rng();
///
/// // Vec of 16 x f32:
/// let v: Vec<f32> = thread_rng().sample_iter(&Standard).take(16).collect();
/// let v: Vec<f32> = rng.sample_iter(Standard).take(16).collect();
///
/// // String:
/// let s: String = rng.sample_iter(&Alphanumeric).take(7).collect();
/// let s: String = rng.sample_iter(Alphanumeric).take(7).collect();
///
/// // Combined values
/// println!("{:?}", thread_rng().sample_iter(&Standard).take(5)
/// println!("{:?}", rng.sample_iter(Standard).take(5)
/// .collect::<Vec<(f64, bool)>>());
///
/// // Dice-rolling:
/// let die_range = Uniform::new_inclusive(1, 6);
/// let mut roll_die = rng.sample_iter(&die_range);
/// let mut roll_die = rng.sample_iter(die_range);
/// while roll_die.next().unwrap() != 6 {
/// println!("Not a 6; rolling again!");
/// }
/// ```
fn sample_iter<'a, T, D: Distribution<T>>(
&'a mut self, distr: &'a D,
) -> distributions::DistIter<'a, D, Self, T>
where Self: Sized {
fn sample_iter<'a, T, D>(&'a mut self, distr: D) -> distributions::DistIter<'a, D, Self, T>
where D: Distribution<T>, Self: 'a {
distr.sample_iter(self)
}

Expand Down

0 comments on commit 52a9307

Please sign in to comment.