【发布时间】:2021-04-05 00:38:11
【问题描述】:
作为一个有抱负的 rustacean,我一直在研究 Rust 编程语言这本书,在第 13 章中,我试图概括 Cacher 结构,其目的是围绕闭包实现惰性求值。虽然我能够使用泛型将闭包签名推广到具有任何一种输出类型的任何一个参数,但我不知道如何将其推广到具有任意数量参数的闭包。我觉得应该有办法做到这一点。
struct Cacher<'a, Args, V: Clone>
{
calculation: &'a dyn Fn(Args) -> V,
value: Option<V>
}
impl<'a, Args, V: Clone> Cacher<'a, Args, V>
{
fn new(calculation: &'a dyn Fn(Args) -> V) -> Cacher<Args, V> {
Cacher {
calculation: calculation,
value: None,
}
}
fn value(&mut self, arg: Args) -> V {
// all this cloning is probably not the best way to do this
match self.value.clone() {
Some(v) => v,
None => {
let v = (self.calculation)(arg);
self.value = Some(v.clone());
v
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let mut cached_func = Cacher::new(&(|asd| asd + 1));
assert_eq!(cached_func.value(1), 2);
assert_eq!(cached_func.value(4), 2);
}
#[test]
fn it_works_too() {
// compiler hates this
let mut cached_func = Cacher::new(&(|asd, qwe| asd + qwe));
assert_eq!(cached_func.value(1, 1), 2);
assert_eq!(cached_func.value(4, 1), 2);
}
}
【问题讨论】:
-
泛型 Args 也是元组的占位符。
-
嗯,首先,您可以通过将所有
Clone替换为Copy来摆脱克隆 -
我还要补充一点,标题可能会与另一种称为 Higher-Kinded Types 的特性混淆,这是函数式程序员对 Rust 的强烈要求的特性。所以,你应该改变标题。
标签: rust