范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

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
Vue3组件开发(二)搭建表格编辑系统组件集成通过前文的学习,我们已经用Vite搭建出了Vue3的项目原型。今天,我们将基于这个原型,集成SpreadJS电子表格组件和在线编辑器组件,使其具备Excel公式计算在线导入导出ExVue3组件开发(三)搭建表格编辑系统功能拓展通过环境搭建和组件集成,我们学会使用Vite和SpreadJS,将在线Excel的编辑功能集成在Vue3项目中。本章,我将带领大家继续扩展Vue3这个项目原型,实现数据绑定模板文件AMD更新三款锐龙CPU,3900XT3800XT3600XT已确定!价格不变Hello大家好,我是兼容机之家的小牛。虽然很多人抱怨英特尔代代挤牙膏,但不得不承认,本月发布的十代酷睿处理器性能表现还算不错,逼得AMD不得不采取降价措施。目前看来降价是有一定效Win102020年5月更新发布,最低配置要求给出,自家Surface用不上Hello大家好,我是兼容机之家的小牛。微软在昨天开始向用户正式推送Windows10的2020年5月更新,此次更新包含了Cortana应用Windows搜索等应用的改进,是今年上三款8核CPU对比英特尔i710700K真香?不,这款CPU性价比更高Hello大家好,我是兼容机之家的小牛。英特尔十代酷睿处理器陆陆续续上市了,某些电商平台已经开启预售,其中i710700K预售价高达3299元,乍看之下这也太贵了,然而事实并非如此十代酷睿i5要抽奖不仅是体质,散热也有别Hello大家好,我是兼容机之家的小牛。英特尔在上月正式发布了第十代桌面级处理器,首发包括有酷睿i9以及奔腾赛扬系列在内的32个型号。不过根据最新的消息显示,十代酷睿i5的部分型号AMD锐龙93900XT现身跑分数据库参数提升不大,就等价格了Hello大家好,我是兼容机之家的小牛。AMD在去年年中带来了最新的三代锐龙处理器,随后一年中,三代锐龙凭借着超强的性能和出色的性价比,收获了众多粉丝的喜爱,在市场占比上也有了巨大AMDB550主板导购!3片爆款网红板预定,其中微星的那款最漂亮Hello大家好,我是兼容机之家的小牛。最新消息,AMDB550芯片组主板将在下个月16日正式发售,我们马上就可以买到廉价的支持PCIe4。0的主板了。自从去年AMD发布三点锐龙处华硕高管曝光AMD新款处理器,将于6月正式上市!难道是4代锐龙?Hello大家好,我是兼容机之家的小牛。英特尔十代酷睿处理器才刚发布,AMD就扛不住压力了,准备在今年六月份发布新款锐龙处理器。根据华硕电脑中国区总经理的爆料,AMD最新的CPU将闪存技术进步还是倒退?QLC将成主流,PLC技术正在研发Hello大家好,我是兼容机之家的小牛。固态硬盘现在已经是基本每台电脑的必备硬件了,略懂一些的用户可能清楚,目前主流的闪存NAND颗粒是TLC的,而QLC颗粒的技术也比较成熟,出现2020年最新桌面CPU天梯图!收录英特尔10代酷睿AMD全系处理器Hello大家好,我是兼容机之家的小牛。英特尔十代酷睿处理器已悉数公布,首批上市的4款处理器大家都可以通过各种渠道购买,部分Z490B460主板渠道能拿到货。这4款处理器分别是i5