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

来源:互联网 发布:fifaol3数据库 编辑:程序博客网 时间:2024/06/14 00:43

从网上摘录了一些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;    }}//Barstruct Bar;impl Bar {    fn calc(&self,i:i32)->i32{        i+5    }    fn calc_static(i:i32)->i32{        i+7    }}//funcfn func(i: i32) -> i32 {    i+6}//mainfn 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();}
0 0
原创粉丝点击