问题概述

值缓存是一种更加广泛的实用行为,我们可能希望在代码中的其他闭包中也使用他们。然而,目前 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

测试通过

【Rust】使用HashMap解决官方文档中的闭包限制的更多相关文章

  1. swift官方文档中的函数闭包是怎么理解的?

    官方文档中的16页: numbers.map({ (number: Int) -> Int in let result = * number return result }) 不知道这个怎么用, ...

  2. swift官方文档中的switch中case let x where x.hasSuffix("pepper")是什么意思?

    在官方文档中,看到这句.但不明白什么意思. let vegetable = "red pepper" switch vegetable { case "celery&qu ...

  3. 从官方文档中探索MySQL分页的几种方式及分页优化

    概览 相比于Oracle,SQL Server 等数据库,MySQL分页的方式简单得多了,官方自带了分页语法 limit 语句: select * from test_t LIMIT {[offset ...

  4. tensorflow官方文档中的sub 和mul中的函数已经在API中改名了

    在照着tensorflow 官方文档和极客学院中tensorflow中文文档学习tensorflow时,遇到下面的两个问题: 1)AttributeError: module 'tensorflow' ...

  5. 【采坑小计】thanos receiver的官方文档中,并未说明tsdb落盘的配置方式

    官方文档的地址在:https://thanos.io/tip/components/receive.md/ 一开始以为落盘的时间间隔是:--tsdb.retention=15d 实际测试中发现,tha ...

  6. 【原创+译文】官方文档中声明的如何创建抽屉导航栏(Navigation Drawer)

    如需转载请注明出处:http://www.cnblogs.com/ghylzwsb/p/5831759.html 创建一个抽屉导航栏 抽屉式导航栏是显示在屏幕的左边缘,它是应用程序的主导航选项面板.它 ...

  7. Django1.7官方文档中的tutorial——翻译

    写下你的第一个Django应用,第一部分 让我们通过例子来学习. 通过这篇指南,我们将会带你浏览一遍一个基本投票应用的创建. 它由两部分组成: 1一个让人们查看投票和进行投票的公共站点 2一个让你添加 ...

  8. Vue官方文档中的camelCased (驼峰式) 命名与 kebab-case

    因为html特性中 元素的 prop是不区分大小写的 所以不管html中怎么大写小写变化,下面的组件的prop应该写成小写 Vue中有这样一种设定: props中如果使用为kebab-case命名方式 ...

  9. 摘录ECMAScript官方文档中重要的两段话

    Every object created by a constructor has an implicit reference (called the object’s prototype) to t ...

随机推荐

  1. Zookeeper 的典型应用场景?

    Zookeeper 是一个典型的发布/订阅模式的分布式数据管理与协调框架,开发人员 可以使用它来进行分布式数据的发布和订阅. 通过对 Zookeeper 中丰富的数据节点进行交叉使用,配合 Watch ...

  2. C语言之API

    C语言之API 1.输入(控制台输入) scanf("%d,%d",&a,&b); 2.输出(打印数值) printf("max=%d\n",c ...

  3. SQL语句之Column 'Status' in where clause is ambiguous错误

    问题: AND created_by IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) limit 0, 10]; Column 'created_by' in where cla ...

  4. Citus 分布式 PostgreSQL 集群 - SQL Reference(手动查询传播)

    手动查询传播 当用户发出查询时,Citus coordinator 将其划分为更小的查询片段,其中每个查询片段可以在工作分片上独立运行.这允许 Citus 将每个查询分布在集群中. 但是,将查询划分为 ...

  5. 手把手教你撸个vue2.0弹窗组件

    手把手教你撸个vue2.0弹窗组件 在开始之前需要了解一下开发vue插件的前置知识,推荐先看一下vue官网的插件介绍 预览地址 http://haogewudi.me/kiko/inde... 源码地 ...

  6. 网络安全—xss

    1.xss的攻击原理 需要了解 Http cookie ajax,Xss(cross-site scripting)攻击指的是攻击者往Web页面里插入恶意html标签或者javascript代码.比如 ...

  7. 多态polymorphism,向上转型和动态方法调度有什么用?

    多态有什么用?马 克  -   t   o - w   i  n:https://blog.csdn.net/qq_44639795/article/details/103117332我给大家想了两个 ...

  8. PAT B1002写出这个数

    读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式: 每个测试输入包含 1 个测试用例,即给出自然数 n 的值.这里保证 n 小于 1. 输出格式: 在一行内输出 n 的 ...

  9. 小程序tab栏可滑动,可点击居中demo

    效果图: 代码: <view class="container"> <!-- tab导航栏 --> <!-- scroll-left属性可以控制滚动条 ...

  10. spring-aop相关概念

    如果下面有疑问请看完动态代理技术的分析 Aop术语: Target(目标对象):要被增强的方法的对象 Proxy(代理对象):简单的说就是对目标对象进行增强的代理类 Joinpoint(连接点):可以 ...