diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index ada0c1ebece..5ed40c4c7c5 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -182,6 +182,12 @@ pub trait Distribution { /// 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` is impl'd for `&D` where `D: Distribution`, + /// 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 /// /// ``` @@ -203,8 +209,8 @@ pub trait Distribution { /// 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, @@ -229,8 +235,8 @@ impl<'a, T, D: Distribution> Distribution 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, } @@ -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() { @@ -350,4 +357,22 @@ mod tests { let results: Vec = 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 + '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); + } } diff --git a/src/lib.rs b/src/lib.rs index 3b59f25086d..004e69c6bda 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -215,26 +215,24 @@ pub trait Rng: RngCore { /// let mut rng = thread_rng(); /// /// // Vec of 16 x f32: - /// let v: Vec = thread_rng().sample_iter(&Standard).take(16).collect(); + /// let v: Vec = 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::>()); /// /// // 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>( - &'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, Self: 'a { distr.sample_iter(self) }