Add an iterator to Distribution#361
Conversation
|
I also added use rand::{thread_rng, Rng};
use rand::distributions::{Alphanumeric, Range, Uniform};
let mut rng = thread_rng();
// Vec of 16 x f32:
let v: Vec<f32> = thread_rng().sample_iter(&Uniform).take(16).collect();
// String:
let s: String = rng.sample_iter(&Alphanumeric).take(7).collect();
// Combined values
println!("{:?}", thread_rng().sample_iter(&Uniform).take(5)
.collect::<Vec<(f64, bool)>>());
// Dice-rolling:
let die_range = Range::new_inclusive(1, 6);
let mut roll_die = rng.sample_iter(&die_range);
while roll_die.next().unwrap() != 6 {
println!("Not a 6; rolling again!");
} |
dhardy
left a comment
There was a problem hiding this comment.
Looking nice — perhaps it is worth having both methods!
| /// let mut rng = thread_rng(); | ||
| /// | ||
| /// // Vec of 16 x f32: | ||
| /// let v: Vec<f32> = thread_rng().sample_iter(&Uniform).take(16).collect(); |
There was a problem hiding this comment.
Nice, but lets not promote bad styles in examples by creating a local rng handle then not using it.
There was a problem hiding this comment.
I wanted to show that it was also possible to use thread_rng() directly. But yes, bad style. Will change.
There was a problem hiding this comment.
I think most people will figure that out.
| /// } | ||
| /// ``` | ||
| fn sample_iter<'a, T, D: Distribution<T>>(&'a mut self, distr: &'a D) | ||
| -> distributions::DistIter<'a, D, Self, T> where Self: Sized |
There was a problem hiding this comment.
Interesting that this takes the distribution by reference while sample takes it by value. I'm not saying this is wrong. If we have both, then distr.iter(&mut rng) is still an option when passing by reference is required, so this could take the distribution by value (which would consume die_range above but only if the & is removed — we also implement Distribution for the references).
There was a problem hiding this comment.
I am not sure we can have both, because the iterator expects an reference instead of something owned. Or do we want to use some sort of Cow or MaybeOwned trick?
There was a problem hiding this comment.
I think it will work if you just change to distr: D here; essentially Distribution::iter receives a reference from this function stack.
There was a problem hiding this comment.
error[E0597]: `distr` does not live long enough
--> src/lib.rs:414:9
|
414 | distr.sample_iter(self)
| ^^^^^ borrowed value does not live long enough
415 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the method body at 411:5...
--> src/lib.rs:411:5
|
411 | / fn sample_iter<'a, T, D: Distribution<T>>(&'a mut self, distr: D)
412 | | -> distributions::DistIter<'a, D, Self, T> where Self: Sized
413 | | {
414 | | distr.sample_iter(self)
415 | | }
| |_____^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
There was a problem hiding this comment.
Sorry, of course the iterator is returned from sample_iter!
|
Do you want to do the honours of merging today (and I the rebasing...)? |
Add an iterator to `Distribution`
This tries to solve the same problem as #275, having a nice way to sample from distributions using an iterator. See also #58.
I have added a
sample_itermethod toDistributionfor now. But I don't mind if it is a method onRnginstead, or on both...With benchmarks similar to those in #275, the results are all over the place. In all situations it is slightly slower than
iter::repeat, but usually not by more than a couple of percent. The exception isUniform, where we use that values generated by the RNG directly:Example of using
Distribution::sample_iterinstead ofRng::gen_iter: