1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//零成本抽象到底是什么意思?"他们使得代码看起来更高级,但并不为此引入运行时性能损失"
//闭包和迭代器是 Rust 受函数式编程语言观念所启发的功能。他们对 Rust 以底层的性能来明确的表达高级概念的能力有很大贡献。闭包和迭代器的实现达到了不影响运行时性能的程度。这正是 Rust 竭力提供零成本抽象的目标的一部分。

use std::thread;
use std::time::Duration;

fn simulated_expensive_calculation(num: u32) -> u32 {
    println!("calculate is slowly ...");
    thread::sleep(Duration::from_secs(2));

    num
}

pub fn generate_workout(intensity: u32, random_number: u32) {
    //let calculation_closure = |num| {
    let mut calculation_closure = Cacher::new(|num| {
        println!("calculate is slowly ...");
        thread::sleep(Duration::from_secs(2));

        num
    });
    if intensity > 25 {
        //println!("Today, do {} pushups!", simulated_expensive_calculation(intensity));
        //println!("Next, do {} situps!", simulated_expensive_calculation(intensity));
        println!("Today, do {} pushups!", calculation_closure.value(intensity));
        println!("Next, do {} situps!", calculation_closure.value(intensity));
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!("Today, run for {} minutes!", calculation_closure.value(intensity));
        }
    }
}

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
            },
        }
    }
}

#[test]
fn iterator_demonstration() {
    let v1 = vec![1,2,3];
    let mut v1_item = v1.iter();
    assert_eq!(v1_item.next(), Some(&1));
    assert_eq!(v1_item.next(), Some(&2));
    assert_eq!(v1_item.next(), Some(&3));
    assert_eq!(v1_item.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);
}

#[derive(PartialEq, Debug)]//assert_eq中进行比较和打印内容进行的比较
struct Shoe {
    size: u32,
    style: String,
}

fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter()
        .filter(|shoe| shoe.size == shoe_size)//过滤方法
        .collect()//执行迭代过滤,生成新的迭代器,集合
}

#[test]
fn filters_by_size() {
    let shoes = vec![
        Shoe {size: 10, style: String::from("sneaker")},
        Shoe {size: 12, 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!(sum, 18);
}

/// 这是一个字符串搜索方法
///
/// # Example
/// ```
/// let query = "name";
/// let contents = "
/// My Name is Jeff,
/// The City is named \"山城\"
/// ";
/// let result = hello_closures::search(query, contents);
/// assert_eq!(
///     result,
///     [
///         "The City is named \"山城\"",
///     ]
/// )
/// ```
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    contents.lines()
        .filter(|s| s.contains(query))
        .collect()
}