Consider the case where I have a function make_numbers
which should create a string of random numbers, but where I want to decide at runtime (user input) what kind of random number generator should be used. To make it even more difficult, let's assume the make_numbers
function to be generic over the type of numbers to be generated.
I wrote what I want to achieve with pseudo code, and I understand why this doesn't work. However, I don't know what an idiomatic way in Rust could look like to achieve this?
My naive ideas would be:
- Use
Box<Rng>
, but that doesn't work sinceRng
has generic functions. - Use an enum over
StdRng
andXorShiftRng
, but I cannot really think of a nice way to write this.
Can you give me some hints as to what a nice solution of this particular problem would look like?
Note: This question is not so much about the different match arms having different types (solutions could be Box
or enum, as indicated above) - but how to apply these solutions in this case.
extern crate rand;
use rand::{Rng, SeedableRng, StdRng};
use rand::prng::XorShiftRng;
use std::string::String;
use rand::distributions::{Distribution, Standard};
use std::fmt::Display;
// Generic function that should work with any type of random number generator
fn make_numbers<T, R: Rng>(rng: &mut R) -> String
where T: Display, Standard: Distribution<T>
{
let mut s = String::new();
for _i in 0..10 {
s.push_str(format!("_{}", rng.gen::<T>()).as_str());
}
s
}
fn main() {
let use_std = true; // -> assume that this will be determined at runtime (e.g. user input)
// Pseudo code, will not work.
let mut rng = match use_std {
true => StdRng::from_seed(b"thisisadummyseedthisisadummyseed".to_owned()),
false => XorShiftRng::from_seed(b"thisisadummyseed".to_owned())
};
let s = make_numbers::<u8>(&mut rng);
// ... do some complex stuff with s ...
print!("{}", s)
}
error[E0308]: match arms have incompatible types
--> src/main.rs:24:19
|
24 | let mut rng = match use_std {
| ___________________^
25 | | true => StdRng::from_seed(b"thisisadummyseedthisisadummyseed".to_owned()),
26 | | false => XorShiftRng::from_seed(b"thisisadummyseed".to_owned())
| | ------------------------------------------------------ match arm with an incompatible type
27 | | };
| |_____^ expected struct `rand::StdRng`, found struct `rand::XorShiftRng`
|
= note: expected type `rand::StdRng`
found type `rand::XorShiftRng`