简单说说闭包,网上相关知识很多,总结一下。
答:闭包的主要作用是创建抽象行为
答:它是一种匿名函数,可保存为变量,可作为参数,可访问在其定义域的上下文中的值。它应该很短小,编译器通常能推断出其类型
答:可以有三种类型的闭包,都实现了以下trait之一:
Fn:不可变借用
FnMut:可变借用
FnOnce:取得所有权
另外:move关键字:在参数列表前用了move关键字后,强制闭包取得该参数的所有权。
接下来上代码:
1、闭包当作参数的用法
fn fn_clos(func:F,i:i32) where F:FnOnce(i32)-> i32{
println!("{}",func(i) );
}
fn main() {
let i1 = 1;
let i2 = 2;
let clos = |a| {i1+i2+a};
fn_clos(clos,1);
}
再变个花样:
fn f i8> (mut g:T) {
println!("{}", g(1));
}
fn main() {
let mut i1=1;
let i2=2;
f(|a| {
i1=i1+a+i2;
i1
});
}
2、闭包和函数签名
fn main() {
let add = |x, y| x + y;
let mut x = add(5,7);
println!("x={}",x);
type Binop = fn(i32, i32) -> i32;
let bo: Binop = add;
x = bo(10,6);
println!("x={}",x);
}
3、闭包与Struct,有点像委托。具体解释看注释。
struct NumStruct//定义T的类型为Fn
where T:Fn(String,i8)->i8,
{
closure:T,
value : Option,
}
//返回一个NumStruct,并且将闭包传入NumStruct.closure
impl NumStruct where T:Fn(String,i8)->i8, {
fn invoke_closure(arg_closure:T)->NumStruct{
NumStruct{
closure:arg_closure,
value:None,
}
}
fn double_value (&mut self,arg1:String,arg2:i8)->i8{
match self.value {
Some(v)=>v,
None=>{
let v=(self.closure)(arg1,arg2);//调用传入的闭包过程,v是结果
self.value=Some(v);
v
}
}
}
}
fn main() {
let hint_string:String=String::from("input value is:");
let input_value:i8=5;
let mut y=NumStruct::invoke_closure( //将闭包传入NumStruct
|a1:String, a2:i8|{
println!("{}{}",a1,a2);
a2+a2
});
let result=y.double_value(hint_string,input_value);
println!("Double Value={}",result);
}
输出:
4、闭包的捕获可以通过称为“唯一不可变借用”(unique immutable borrow)的特殊借用进行,这种借用不能在语言中的任何其他地方使用,也不能显式写出。它发生在修改可变引用的referent时,如下例所示:
fn main() {
let mut b = false;
let x = &mut b;
{
let mut c = || { *x = true; };
// 下面会报错:
// let y = &x;
c();
}
let z = &x;
println!("{}",z);//输出true
println!("{}",b);//输出true
}