脚本宝典收集整理的这篇文章主要介绍了rust实战系列 - 使用闭包和泛型实现简单的Cache,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
本文主要围绕怎么用rust语言来设计一个cache,期间会用到闭包,泛型。
use std::{cmp::Eq, hash::Hash, collections::HashMap};
struct Cacher<T, U, V>
where T: Fn(U) -> V
{
calculation: T,
value: HashMap<U, V>,
}
上面的代码定义了一个Cacher的结构,同时使用了泛型参数T,U,V; T是一个闭包函数,输入参数U,输出参数V。 字段Cacher.calculation的类型是一个闭包函数,类型为T,Cacher.value的类型是一个hash表,用来存储闭包函数的输入和输出。
这里使用泛型参数,因此可以灵活的处理各种情况,比如
impl<T, U, V> Cacher<T, U, V>
where T: Fn(U) -> V,
U: Eq + Hash + Copy,
V: Copy
{
fn new(cal: T) -> Cacher<T, U, V> {
Cacher {
calculation: cal,
value: HashMap::new()
}
}
fn value(&mut self, value: U) -> V {
let v = self.value.get(&value);
match v {
Some(v) => *v,
None => {
let v = (self.calculation)(value);
self.value.insert(value, v);
v
}
}
}
}
上面的代码为Cacher定义了new方法用来初始化实例,这里通过U作为Hash的key需要实现Eq和Hash两个trait。
Cacher.value 用来获取缓存的值,如果hash表有执行结果则直接返回,否则调用闭包函数计算出结果存放到hash表里面,然后
再取值返回。这里U,V也强制其要求实现Copy trait,因为value函数里面会move U,V类型的值。
**最后一个重点,Cacher::new出来的每个实例,其内部的泛型参数会在编译时实际转换为对应的类型,因此要让cacher支持不同的输入输出闭包,需要重新
Cacher::new一个实例**
#[test]
fn call_with_different_values() {
let mut c = Cacher::new(|a| a);
let mut d = Cacher::new(|a: &str|{a.len()});
c.value(1);
let v2 = c.value(2);
assert_eq!(v2, 2);
let v1 = d.value("str123");
let v2 = d.value("str123456");
assert_ne!(v1, v2);
assert_eq!(v2, 9);
}
上面的代码分别测试了两种情况:
本文主要是在阅读<<Rust权威指南>>中的例子扩展出来的,原文的Cacher例子有两个局限性
以上是脚本宝典为你收集整理的rust实战系列 - 使用闭包和泛型实现简单的Cache全部内容,希望文章能够帮你解决rust实战系列 - 使用闭包和泛型实现简单的Cache所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。