函数式编程:
函数式风格编程通常包括将函数当作参数、将函数作为其他函数的返回值或将函数赋给变量以备之后执行等。
闭包:
一个类似函数,并且可以存储在变量中的结构。闭包拥有很好的运行性能。
闭包可以存入变量或作为参数传递给其他函数的匿名函数。
闭包可以从定义它的作用域中获取值。
迭代器:
处理一系列元素的方法。
闭包:
闭包不要求明确标注参数和返回值的类型,因为闭包永远不会作为公共接口对外暴露。因此编译器能够推导出参数和返回值的类型。但是,一旦编译器推导类型确定了,那么就只能传入该类型的参数。
结构体、枚举或函数参数中使用闭包:
闭包在结构体中必须指明类型,因为结构体中各个字段的类型在定义时就必须确定。每一个闭包实例都有它自己的匿名类型。两个闭包拥有完全相同的签名,它们的类型也被认为是不一样的。
所有的闭包都至少实现了标准库中提供的Fn、 FnMut及FnOnce中的一个trait。
Fn Trait:
Fn的trait约束中添加代表了闭包参数和闭包返回值的类型。
struct Cacher<T>
where T:Fn(u32)->u32
{
calculation:T,
value:Option<u32>
}
泛型T的类型约束是Fn Trait。
闭包捕获上下文环境
闭包可以捕获自己所在的环境并访问自己被定义时的作用域中的变量。
闭包从上下文环境中获取变量有三种方式: 获取所有权、可变借用及不可变借用,三种方式分别被封装在三种不同的Trait中:
FnOnce:闭包必须在定义时取得这些变量的所有权并将它们移动至闭包中。可以通过在参数列标签添加move,
FnMut:可以从环境中可变地借用值并对它们进行修改
Fn:可以从环境中不可变地借用值。
let equal_to_x = move |z| z == x;
迭代器:
迭代器模式允许你依次为序列中的每一个元素执行某些任务
创建一个迭代器:
在Rust中,迭代器是惰性的(layzy)。这也就意味着创建迭代器后,除非你主动调用方法来消耗并使用迭代器,否则它们不会产生任何的实际效果。
terator trait:迭代器trait
pub trait Iterator{
type Item; // 定义关联类型
fn next(&mut self) -> Option<Self::Item>; // Self::Item
}
let v1 = vec![1,2,3];
let mut v1_iter = v1.iter();
assert_eq!(v1_iter.next(),Some(&1)); // 这里所&1,表示所对值1的引用
iter:生成的是一个不可变引用的迭代器
into_iter: 生成一个获取所有权,并返回元素本身的迭代器
iter_mut:返回一个可变引用的迭代器,允许你遍历集合并可能修改其中的元素。
消耗迭代器的方法:
next方法:调用next的方法也被称为消耗适配器 (consuming adaptor)
sum()方法:获取迭代器的所有权并反复调用next来遍历元素,进而导致迭代器被消耗
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
let total: i32 = v1_iter.sum();
assert_eq!(total, 6);
println!("{:?}",v1_iter); // 报错,所有权已经被sum函数占有使用
生成其他迭代器的方法:
map:
let v1: Vec<i32> = vec![1, 2, 3];
let iter_v1:Vec<i32> = v1.iter().map(|x| x + 1).collect();
assert_eq!(iter_v1,vec![2,3,4]);
调用map方法创建新迭代器,接着再调用collect方法将其消耗掉并得到一个动态数组
filter:
fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
shoes.into_iter()
.filter(|s| s.size == shoe_size)
.collect()
}