- 闭包:能够捕获环境的匿名函数
- 使用闭包来创建抽象化的程序行为
- 闭包的类型推断和类型标注
- 使用泛型参数和Fn trait来存储闭包
- Cacher实现的局限性
- 使用闭包捕获上下文环境
- 使用迭代器处理元素序列
- Iterator trail和next方法
- 消耗迭代器的方法
- 生成其他迭代器的方法
- 使用闭包捕获环境
- 使用Iterator trait来创建自定义迭代器
- 使用Counter迭代器的next方法
- 使用其他的Iterator trait方法
- 改进I/O项目
- 使用迭代器代替clone
- 直接使用返回的迭代器
- 使用Iterator trait方法来替代索引
- 使用迭代器适配器让代码更加清晰
- 比较循环和迭代器的性能
closure
main.rs:
use std::thread;
use std::time::Duration;
use std::panic::panic_any;
use std::collections::hash_map::OccupiedEntry;
struct Cacher<T>
where T: Fn(u32) -> u32
{
calculation: T,
value: Option<u32>,
}
impl<T> Cacher<T>
where T: 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
},
}
}
}
fn simulated_expensive_calculation(intensity: u32) -> u32 {
println!("calculation slowly...");
thread::sleep(Duration::from_secs(2));
intensity
}
fn generate_workout(intensity: u32, random_number: u32) {
let mut expensive_result = Cacher::new(|num| {
println!("calculation slowly...");
thread::sleep(Duration::from_secs(2));
num
});
if intensity < 25 {
println!(
"Today, do {} push-ups!",
expensive_result.value(intensity)
);
println!(
"Next, do {} sit-ups",
expensive_result.value(intensity)
)
} else {
if random_number == 3 {
println!("Take a break today! Remember to stay hydrated!");
} else {
println!("Today, run for {} minutes!",
expensive_result.value(intensity)
)
}
}
}
fn main() {
let simulated_user_specified_value = 10;
let simulated_random_number = 7;
generate_workout(
simulated_user_specified_value,
simulated_random_number
);
let x = 4;
let equal_to_x = |z| z == x;
let y = 4;
assert!(equal_to_x(y));
}
#[test]
fn call_with_different_values() {
let mut c = Cacher::new(|a| a);
let v1 = c.value(1);
let v2 = c.value(2);
assert_eq!(v2, 2);
}
iterator
main.rs:
fn main() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
for val in v1_iter {
println!("Got {}", val);
}
let v1: Vec<i32> = vec![1, 2, 3];
let v2: Vec<_> =v1.iter().map(|x| { x + 1 }).collect();
assert_eq!(v2, vec![2, 3, 4]);
}
#[test]
fn iterator_demonstration() {
let v1 = vec![1, 2, 3];
let mut v1_iter = v1.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);
}
#[test]
fn iterator_sum() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
let total: i32 = v1_iter.sum();
assert_eq!(total, 6);
}
lib.rs:
#[derive(PartialEq, Debug)]
struct Shoe {
size: u32,
style: String,
}
fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe>
{
shoes.into_iter()
.filter(|s| s.size == shoe_size)
.collect()
}
#[test]
fn filters_by_size() {
let shoes = vec![
Shoe { size: 10,style: String::from("sneaker") },
Shoe { size: 13,style: String::from("sandal") },
Shoe { size: 10,style: String::from("boot") },
];
let in_my_size = shoes_in_my_size(shoes, 10);
assert_eq!(
in_my_size,
vec![
Shoe { size: 10,style: String::from("sneaker") },
Shoe { size: 10,style: String::from("boot") },
]
);
}
struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.count += 1;
if self.count < 6 {
Some(self.count)
} else {
None
}
}
}
#[test]
fn calling_next_directly() {
let mut counter = Counter::new();
assert_eq!(counter.next(), Some(1));
assert_eq!(counter.next(), Some(2));
assert_eq!(counter.next(), Some(3));
assert_eq!(counter.next(), Some(4));
assert_eq!(counter.next(), Some(5));
assert_eq!(counter.next(), None);
}
#[test]
fn using_other_iterator_trait_methods() {
let sum: u32 = Counter::new().zip(Counter::new().skip(1))
.map(|(a, b)| a * b)
.filter(|x| x & 3 == 0)
.sum();
assert_eq!(18, sum);
}