通过trait reference来保存 函数、closure 的调用入口

本文详细解释了Rust语言中闭包特质Fn、FnMut和FnOnce的区别及使用场景,通过具体的代码示例展示了如何定义和使用这些闭包特质。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从网上摘录了一些Fn,FnMut,FnOnce的说明,具体可以看看这个链接,不过这个是在rust 1.0之前写的,有些东西过时了
http://smallcultfollowing.com/babysteps/blog/2014/11/26/purging-proc/
这个是以前的Fn,FnMut,FnOnce的声明,现在1.2.0已经改变了,不过这个更好理解:

trait Fn<A,R> { fn call(&self, args: A) -> R };
trait FnMut<A,R> { fn call_mut(&mut self, args: A) -> R };
trait FnOnce<A,R> { fn call_once(self, args: A) -> R };

这3个trait的区别就在于self的区别,他们对应了3种不同的函数调用:

  • Fn类似于shared reference,closure不可以改变环境变量
  • FnMut类似于mutable reference,closure可以改变环境变量
  • FnOnce类似于ownership,closure只能调用一次

我们还要知道Fn,FnOnce,FnMut这3个trait的语法糖形式:
FnMut(&String) -> uint
这个对应了:
<'a> FnMut<(&'a String,), uint>

知道了这个语法糖下面的代码就比较容易理解了,Foo将实现了trait Fn(i32)->i32的函数或者closure保存在成员变量func里,需要调用的时候通过(self.func)(xxx);的形式调用,注意(self.func)要用括号,不然编译器会把self.func单做是impl实现的method

//F是满足Fn(i32)->i32这个trait的所有closure,函数和struct的static函数
struct Foo<F:Fn(i32)->i32> {
    func: F,
    data:i32
}

impl<F:Fn(i32)->i32> Foo<F> {
    fn new(f:F)->Foo<F>{
        Foo{func:f,data:3}
    }

    fn print(&self){
        println!("data:{}", self.data);
        //注意调用方式类似于c++的函数指针,self.func要用()再调用
        println!("result of func:{}", (self.func)(3));
    }

    fn calc(&mut self,i:i32){
        self.data = (self.func)(5) + i;
    }
}

//Bar
struct Bar;

impl Bar {
    fn calc(&self,i:i32)->i32{
        i+5
    }

    fn calc_static(i:i32)->i32{
        i+7
    }
}

//func
fn func(i: i32) -> i32 {
    i+6
}

//main
fn main() {

    let f1 = Foo::new(|i|i+3);
    f1.print();


    let f2 = Foo::new(Bar::calc_static);
    f2.print();

    //Fn(i32)->i32只能用于匹配函数,closure和struct的static 函数
    // let b1 = Bar;
    // let f3 = Foo::new(b1.calc);
    // f3.print();

    let f4 = Foo::new(func);
    f4.print();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值