Рассмотрим случай, когда у меня есть функция make_numbers
, которая должна создавать строку случайных чисел, но где я хочу решить во время выполнения (пользовательский ввод), какой тип генератора случайных чисел следует использовать.Чтобы сделать это еще сложнее, давайте предположим, что функция make_numbers
является общей для типа генерируемых чисел.
Я написал то, что хочу достичь с помощью псевдокода, и я понимаю, почему это не такт работа.Тем не менее, я не знаю, как может выглядеть идиоматический способ в Rust для достижения этой цели?
Мои наивные идеи были бы:
- Использование
Box<Rng>
, но это не такне работает, так как Rng
имеет общие функции. - Используйте перечисление для
StdRng
и XorShiftRng
, но я не могу придумать хороший способ написать это.
Можете ли вы дать мне несколько советов о том, как будет выглядеть хорошее решение этой конкретной проблемы?
Примечание. Этот вопрос не столько о разных спичечных плечах, имеющих разные типы (решения)может быть Box
или enum, как указано выше), но как применять эти решения в этом случае.
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`