-
闭包
可以捕获其所在环境的匿名函数, 闭包是一个函数,该函数的定义可以赋给一个变量
例子—生成自定义运动计划的程序
目标:不让用户发生不必要的等待
fn main(){
//创建闭包
let expensive_closure = |num1, num2|{
num1+num2
};
let b = expensive_closure(11, 12);//调用闭包
println!("{}", b);//23
}
闭包不要求标注参数和返回值的类型,可以自行推断,当然也可以手动标出
fn main(){
let expensive_closure = |num1, num2|{
num1+num2
};
let b = expensive_closure(11, 12);//第一个调用已经确定了闭包的参数和返回值类型,并且不能被改变
let c = expensive_closure(11.0, 12.0);//报错,因为已经推断出了i32, i32
}
解决避免多次执行一个耗时函数我们可以使用闭包并配合struct,struct持有闭包及其调用结果
struct Cacher<T>
where T:Fn(u32)->u32
{
calculation:T,
value:Option<u32>,
}
impl<T> Cacher<T>
where T:Fn(u32)->u32{//Fn(u32)->u32 就是一种闭包类型
fn new(calculation:T)->Cacher<T>{
Cacher{
calculation,
value:None,
}
}
fn value(&mut self, arg:u32)->u32{
match self.value{
Some(v)=>v,
None=>{
let v = (self.calculation)(arg);
self.value = Some(v);
v
},
}
}
}
闭包可以捕获与闭包处在相同环境的变量,函数不可以
move关键字可以强制闭包取得它所使用的环境值的所有权
fn main(){
let a = 2;
let test1 = |number|{number};
let b = test1(a);//成功捕获到环境变量a
println!("{}", a);//此时a的所有权并没有被闭包夺走
}
fn main(){
let x = vec![1, 2, 3];
let equal_to_x = move |z| z==x;
println!("{:#?}", x);//move将环境变量的所有权占有了
let y = vec![1, 2, 3];
assert!(equal_to_x(y))
}
-
迭代器
遍历每一个元素 : .iter()
iterator trait仅要求实现一个方法:next
next:用一次往下走一项
每次返回迭代器的一项
返回结果包裹在Some里
迭代结束,返回None
可以直接在迭代器上调用next方法
fn main(){
let vec = vec![1, 2, 3];
let mut v1_iter = vec.iter();
assert_eq!(v1_iter.next(), Some(&1));
assert_eq!(v1_iter.next(), Some(&2));
assert_eq!(v1_iter.next(), Some(&3));
assert_eq!(v1_iter.next(), None);
}
sum()函数
fn main(){
let vec = vec![1, 2, 3];
let v1_iter = vec.iter();
let total:i32 = v1_iter.sum();
println!("sum = {}", total);//6
}
map()方法将一个迭代器变成另一个迭代器
fn main(){
let vec = vec![1, 2, 3];
let v1_iter = vec.iter();
let iter_map:Vec<_> = v1_iter.map(|x|x+1).collect();
println!("{:#?}", iter_map);//2, 3, 4
}
filter方法:
接收一个闭包,这个闭包在遍历迭代器每个元素时,返回bool类型
如果闭包返回true:当前元素将会包含在filter产生的迭代器中,若false则不会包含在filter产生的迭代器中