rust(6) 闭包

//语法格式    和函数fn 有点像。

复制代码
fn  add_one_v1 (x:i32)->i32 { x+1 }
fn main(){
    let add_one_v2 = |x:i32|->i32{  x+1 };
    let add_one_v3=|x| {x+1};
    let add_one_v4=|x| x+1;

    let a=add_one_v1(5);//使用函数加1
    let b = add_one_v2(5);
    let c = add_one_v3(5);
    let d = add_one_v4(5);
  //闭包定义会为每个参数和返回值类型推导一个具体的类型,但是,,,不能推导两次,下面的会报错
  let example_closure=|x| x;
  let e = example_closure(String::from("nihao"));
  let f  = example_closure(5);
}
复制代码

一个示例

复制代码
//实现一个缓存,只处理第一次传入的值,并保存。
fn main(){
    let mut c = Cacher::new(|x| x+1);
    let v1 = c.value(1);
    let v2 = c.value(100);
    println!("v1 is {},v2 is {}",v1,v2);
}
struct Cacher<T> where T:Fn(u32)->u32
{
    calcuation:T,
    value:Option<u32>,
}
impl<T> Cacher<T> where T:Fn(u32)->u32 {
    fn new(calcuation:T)-> Cacher<T>{
        Cacher { 
            calcuation,
             value:None,
            }
    }
    fn value(&mut self,arg:u32)->u32{
        match self.value {
            Some(v) =>v, 
            None => {
                let v = (self.calcuation)(arg);
                self.value=Some(v);
                v
            }
        }
    }
}
复制代码

闭包可以通过三种方式捕获其环境,它们直接对应到函数获取参数的三种方式:不可变借用,可变借用和获取所有权。闭包会根据函数体中如何使用被捕获的值决定用哪种方式捕获。

  1. FnOnce 适用于能被调用一次的闭包,所有闭包都至少实现了这个 trait,因为所有闭包都能被调用。一个会将捕获的值移出闭包体的闭包只实现 FnOnce trait,这是因为它只能被调用一次。
  2. FnMut 适用于不会将捕获的值移出闭包体的闭包,但它可能会修改被捕获的值。这类闭包可以被调用多次。
  3. Fn 适用于既不将被捕获的值移出闭包体也不修改被捕获的值的闭包,当然也包括不从环境中捕获值的闭包。这类闭包可以被调用多次而不改变它们的环境,这在会多次并发调用闭包的场景中十分重要。
复制代码
fn main(){
/*     let x =4;
    let equal_to_x = |z| z==x;
    let y = 4 ;
    assert!(equal_to_x(y)); */
    let x = vec![1,2,3];
    let equal_to_x =move |z| z==x;
    println!("x is {:?}",x);//这里会报错,因为x在上一行已经呗借用了,这里已经失效了。
    let y = vec![1,2,3];
    assert!(equal_to_x(y));

}
复制代码

 

 

posted @   丢丢乱射  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
点击右上角即可分享
微信分享提示