作者:不要芹菜味 | 来源:互联网 | 2022-12-09 12:58
我正在努力理解处理特定抽象问题的正确方法.让我用我目前的斗争thread_rng
作为更大问题的代理人.
我想将随机数生成器的单个实例传递给各种函数.我不希望他们知道结构的实现(或大小!),只需使用其定义的接口.今天是thread_rng()
,但也许明天它需要成为其他东西,我不想重写使用它的代码.
显而易见的事情是使用这个rand::Rng
特性,但传递它似乎真的很粗糙(至少是印刷品)重量级.如果我理解正确,我通过我的特质实现结构的任何东西都需要使用泛型来单形化,更正吗?这是人们如何做到这一点,还是有另一种方式?
代码示例:
extern crate rand;
use rand::prelude::*;
mod sim {
use rand::Rng;
pub fn generate_numbers(r: &mut TRng) -> i32 {
r.gen_range(42, 45)
}
}
fn main() {
let mut rng = thread_rng();
let result = sim::generate_numbers(&mut rng);
println!("Result: {}", result);
}
这在一个受限制的示例中看起来很好,但在我的代码库中,我可能会在最终到达实际对其执行的叶函数之前,将RNG向下传递通过模块的多层函数调用.两者之间的一切都得到了泛滥的大量粉饰.我只能想象当我想要抽象的东西时,它看起来有多糟糕.
什么是必须Rust方式来做到这一点?也许定义一个结构来保存这种上下文,并将特征放在一个盒子里?我不知道如何做到这一点(不能包装特征Rng
),而不使包含结构本身通用 - 这也是在我必须通过这个包含结构的地方乱丢垃圾.
也许我只是抱怨泛型,因为它们让我想起了C++模板.
1> Sebastian Re..:
您可以使用新的impl trait短语法:
mod sim {
use rand::Rng;
pub fn generate_numbers(r: &mut impl Rng) -> i32 {
r.gen_range(42, 45)
}
}
这并没有真正改变代码的含义,但它使它不那么重量级.