Rust学习笔记(四十)闭包实例(简单缓存)
针对三十九节中Cacher实现的限制,我们可以用HashMap代替结构体中的单个value。HashMap的key就是我们传入闭包的参数,value就是闭包执行的结果。当我们调用value方法时,首先看HashMap中有无与其对应的缓存,有则直接返回,无需执行闭包;没有则执行闭包,将传入的参数和返回的结果以键值对插入HashMap,最后返回结果。//src/lib.rs pub mod cache { use std::collections::HashMap; use std::hash::Hash; //F是闭包的类型,T是闭包的参数类型,R是闭包的返回类型 pub struct Cacher where T: Eq + Hash + Clone,//由于T还是HashMap的key,所以它要求T实现了Eq + Hash + Clone三个trait F: Fn(&T) -> R,//闭包的参数是T的引用,因为T传入闭包后,还需要将它和闭包的结果插入HashMap,如果传入的不是引用,那它的所有权移动至闭包内,导致后面无法插入HashMap { values: HashMap,//缓存闭包参数和闭包结果的键值对 value_setter: F,//闭包 } impl Cacher where T: Eq + Hash + Clone, F: Fn(&T) -> R, { pub fn new(value_setter: F) -> Cacher { Cacher { values: HashMap::new(), value_setter: value_setter, } } pub fn value(&mut self, arg: T) -> &R { //HashMap中有想要的值,直接取出并返回,不需要调用闭包 if self.values.contains_key(&arg) { self.values.get(&arg).expect("msg") } else {//HashMap中没有想要的值 //执行闭包,计算出想要的值 let value = (self.value_setter)(&arg); //由于后面要把参数和结果插入HashMap,所以参数和结果所有权被移动,无法直接返回 //只能重新从HashMap中通过参数的引用取出来再返回 //但是如果参数插入HashMap,那么它的所有权被移动,就无法使用它get值了 //所以这里先clone一个参数,然后把它当作key插入HashMap,这样后面依然能使用参数get对应的结果 let key = arg.clone(); self.values.insert(key, value); //返回该参数对应的结果 self.values.get(&arg).expect("msg") } } } }//src/main.rs use std::{thread, time::Duration}; use adder::cache;//项目(package)名::模块名 fn main() { let mut cache = cache::Cacher::new(|a: &String| -> i32 { println!("参数是{}的闭包执行了。", a); let b: i32 = a.parse().expect("msg"); b }); println!("获取缓存的值:{}", cache.value(String::from("1"))); println!("获取缓存的值:{}", cache.value(String::from("1"))); println!("获取缓存的值:{}", cache.value(String::from("1"))); println!("获取缓存的值:{}", cache.value(String::from("4"))); println!("获取缓存的值:{}", cache.value(String::from("2"))); println!("获取缓存的值:{}", cache.value(String::from("2"))); println!("获取缓存的值:{}", cache.value(String::from("5"))); }
执行以上代码:参数是1的闭包执行了。 获取缓存的值:1 获取缓存的值:1 获取缓存的值:1 参数是4的闭包执行了。 获取缓存的值:4 参数是2的闭包执行了。 获取缓存的值:2 获取缓存的值:2 参数是5的闭包执行了。 获取缓存的值:5
可以看出我们获取了3次字符串1对应的值,但是参数是1的闭包只执行了1次。 同理,4、2、5也是一样的。
注:由于教程没有给出此方案的代码,所以以上代码都是基于个人理解实现的,若有错误,欢迎大家批评指正。使用闭包捕获环境
闭包可以访问定义它的作用域内的变量,而普通函数则不能。 例:fn main() { let x = 4; let equal_to_x = |z| z == x; let y = 4; assert!(equal_to_x(y)); }
以上代码可以正常执行。但如果把闭包换为函数:fn main() { let x = 4; fn equal_to_x(z: i32) -> bool { z ==x } let y = 4; assert!(equal_to_x(y)); }
运行会报错:can"t capture dynamic environment in a fn item 但是捕获环境会产生内存开销。闭包从所在环境捕获值的方式
与函数获得参数的三种方式一样:取得所有权:FnOnce。将环境中值的所有权移动进闭包,其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实,所以它只能被调用一次。可变借用:FnMut。不可变借用:Fn
创建闭包时,通过闭包对环境值的使用,Rust推断出具体使用哪个trait:所有的闭包都实现了FnOnce,因为所有闭包都至少会被调用一次没有移动捕获变量的实现了FnMut无需可变访问捕获变量的闭包实现了Fnmove关键字
在参数列表前使用move关键字,可以强制闭包取得它所使用的环境值的所有权,适用于: 当我们需要将闭包传递给新线程以移动数据使其归新线程所有时,此技术最管用。 例:fn main() { let x = vec![1, 2, 3]; let equal_to_x = move |z| z == x; println!("{:?}", x); equal_to_x(vec![1, 2, 3]); }
所有权被移动,后面在println中再次使用会报错。最佳实践
当指定Fn trait bound时之一时,首先用Fn,基于闭包体里的情况,如果需要FnOnce或FnMut时,编译器会给出提示。
后ERP时代,如何利用BI管理信息?你这个可以写篇论文来讨论的问题,现在想要在这里面几百字给你讲清楚,实在不容易。传统的ERP主要是用于收集数据,管理数据,而bi主要是用于分析数据,呈现数据,两者之间的功能和定位是不
氟元素的发掘之路时刻与死神相伴的化学家们氟(fluorine)是一种非金属化学元素,化学符号为F,原子序数为9。氟是卤族元素之一,属周期系A族,在元素周期表中位于第二周期。氟元素的单质是F,它是一种淡黄色有剧毒的气体。氟
最近比较火的国外凤凰系统Windows11,效果不错,值得使用PhoenixLiteOS11ProPlus(Build22000。493)官方网址httpsphoenixliteos。com安装,汉化视频已同步出教程,请关注收藏!系统设置汉化
GO语言(二十)编写Web应用程序(中)编辑页面wiki需要能编辑页面。让我们创建两个新的处理程序一个命名editHandler为显示编辑页面表单,另一个命名saveHandler为保存通过表单输入的数据。首先,我们将它
AI被用于俄乌战争细思极恐,人工智能人脸识别技术被首次用于俄乌战争了,而背后的数据源头来自于社交软件。近日,乌克兰方面宣布,俄罗斯近卫第8集团军司令莫尔德维乔中将在乌克兰的切尔诺巴耶夫卡被击毙。这将
最高涨一千!小牛电动也涨价,刚被315点名,网友转嫁消费者继各大电动汽车纷纷涨价后,主打俩轮电动车的小牛电动也宣布涨价。3月21日,小牛电动公告称,受上游锂电等原材料(价格)大幅上涨,将于4月1日对全系锂电产品零售指导价进行一次上调,上调
定位紧凑级轿车,售价25。78Polestar极星作为一个拥有纯正北欧血统的的新能源汽车品牌,凭借插电混动的跑车Polestar1奠定了豪华性能的品牌定位,从而让众人开始关注这个新型的新能源汽车品牌,而今天小编
技术研发鏖战正酣大运新能源高端家轿SUV即将亮相记者杨红义柴瑜竟沿着中心城区河东东街延长线驱车行驶,大运汽车新能源乘用车生产基地北门口,一栋六层高L型钢结构大厦刚刚封顶,挥舞着长臂的塔吊忙个不停,施工者正紧张有序施工这座大厦从去
10。89万起售,价格屠夫长安UNIV,能否振兴UNI家族?现在T和K的月销量可以保持在平均一万台这块儿的,大约是T卖7000台,K卖3000台。V这个车上市初期的月销量保持在万台以上是没问题的,首月月销量甚至有可能突破2万台,之后会逐渐降
神州数码签字中国移动21年挖贝网3月21日,神州数码(000034)发布公告,公司下属控股子公司北京神州数码云科信息技术有限公司(以下简称云科信息技术)为中国移动2021年至2022年人工智能通用计算设备集
学会通知丨关于开展2022年最美科技工作者学习宣传活动的通知学会各分支机构省级人工智能学会会员单位为大力弘扬科学家精神,激发科技工作者的荣誉感自豪感责任感,团结凝聚广大科技工作者以强大的创新自信奋进高水平科技自立自强新征程,根据科协发宣字2