【Rust】使用HashMap解决官方文档中的闭包限制
问题概述
值缓存是一种更加广泛的实用行为,我们可能希望在代码中的其他闭包中也使用他们。然而,目前 Cacher 的实现存在两个小问题,这使得在不同上下文中复用变得很困难。
第一个问题是 Cacher 实例假设对于 value 方法的任何 arg 参数值总是会返回相同的值。也就是说,这个 Cacher 的测试会失败:
《rust程序设计语言》13章闭包内容提出的问题
#[test] fn call_with_different_values() { let mut c = Cacher::new(|a| a); let v1 = c.value(1); let v2 = c.value(2); assert_eq!(v2, 2); }
具体代码请在《rust程序设计语言》第13章第一节 Cacher
实现的限制 中找到。
解决思路
尝试修改 Cacher 存放一个哈希 map 而不是单独一个值。哈希 map 的 key 将是传递进来的 arg 值,而 value 则是对应 key 调用闭包的结果值。
相比之前检查 self.value 直接是 Some 还是 None 值,现在 value 函数会在哈希 map 中寻找 arg,如果找到的话就返回其对应的值。如果不存在,Cacher 会调用闭包并将结果值保存在哈希 map 对应 arg 值的位置。
《rust程序设计语言》13章闭包内容提出的解决思路
解决方案
更改Cacher结构体的类型
use std::collections::HashMap; struct Cacher<T> where T: Fn(u32) -> u32, { calculation: T, value: HashMap<u32, u32>, }
将之前储存单一u32类型的 value字段 替换成 HashMap类型,此HashMap的key和value都为u32类型。
更改chacher结构体的方法
impl<T> Cacher<T> where T: Fn(u32) -> u32, { fn new(calculation: T) -> Cacher<T> { Cacher { calculation, value: HashMap::new(), } } fn value(&mut self, arg: u32) -> u32 { match self.value.get(&arg) { Some(v) => *v, None => { let v = (self.calculation)(arg); self.value.insert(arg, v); arg } } } }
new方法中返回的Cacher实例,value字段 不再为Option<u32>类型,取而代之的是一个 被初始化的HashMap,用于存放 不同参数的结果缓存。
value方法中,不再直接匹配结构体的value字段,而是通过 参数 去value字段的 HashMap 中找到储存的值并返回,要是找不到则在HashMap中插入 key值为传入参数,value值为结构体闭包调用参数所得的结果。
测试结果
fn main() { let mut cal = Cacher::new(|num| { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num }); println!("{}", cal.value(1)); println!("{}", cal.value(2)); println!("{}", cal.value(1)) }
cargo run Compiling closure v0.1.0 (D:\project\rust\closure) Finished dev [unoptimized + debuginfo] target(s) in 0.66s Running `target\debug\closure.exe` calculating slowly... 1 calculating slowly... 2 1
测试通过
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署