basic_example/example/closures/
mod.rs

1use std::{thread, cmp, hash};
2use std::time::Duration;
3use std::collections::HashMap;
4
5pub fn run(){
6    let simulated_user_specified_value = 10;
7    let simulated_random_number = 7;
8
9    generate_workout(
10        simulated_user_specified_value,
11        simulated_random_number
12    );
13}
14
15//fn simulated_expensive_calculation(intensity: u32) -> u32 {
16//    println!("calculating slowly...");
17//    thread::sleep(Duration::from_secs(2));
18//    intensity
19//}
20
21fn generate_workout(intensity: u32, random_number: u32) {
22//    let expensive_result =
23//        simulated_expensive_calculation(intensity);
24
25//    let expensive_closure = |num| {
26//        println!("calculating slowly...");
27//        thread::sleep(Duration::from_secs(2));
28//        num
29//    };
30
31    let mut expensive_closure = Cacher::new(|num|{
32        println!("calculating slowly...");
33        thread::sleep(Duration::from_secs(2));
34        num
35    });
36
37//    if intensity < 25 {
38//        println!("Today, do {} pushups!", expensive_closure(intensity));
39//        println!("Next, do {} situps!", expensive_closure(intensity));
40//    } else {
41//        if random_number == 3 {
42//            println!("Take a break today! Remember to stay hydrated!");
43//        } else {
44//            println!("Today, run for {} minutes!", expensive_closure(intensity));
45//        }
46//    }
47
48    if intensity < 25 {
49        println!("Today, do {} pushups!", expensive_closure.value(intensity));
50        println!("Next, do {} situps!", expensive_closure.value(intensity));
51    } else {
52        if random_number == 3 {
53            println!("Take a break today! Remember to stay hydrated!");
54        } else {
55            println!("Today, run for {} minutes!", expensive_closure.value(intensity));
56        }
57    }
58
59    let x = vec![1, 2, 3];
60    let equal_to_x = move |z| z == x;
61    let y = vec![1, 2, 3];
62    println!("{}", equal_to_x(y))
63}
64
65//所有的闭包都实现了 trait Fn、FnMut 或 FnOnce 中的一个
66// 闭包有一个 u32 的参数并返回一个 u32,这样所指定的 trait bound 就是 Fn(u32) -> u32
67
68// 定义一个 Cacher 结构体来在 calculation 中存放闭包并在 value 中存放 Option 值
69
70// 第一阶段:只针对单个数据u32有效
71//struct Cacher<T>
72//    where T: Fn(u32) -> u32
73//{
74//    calculation: T,
75//    value: Option<u32>,
76//}
77
78//impl<T> Cacher<T> where T: Fn(u32) -> u32 {
79//    fn new(calculation: T) -> Cacher<T> {
80//        Cacher {calculation, value: None}
81//    }
82//
83//    fn value(&mut self, arg: u32) -> u32 {
84//        match self.value {
85//            Some(v) => v,
86//            None => {
87//                let v = (self.calculation)(arg);
88//                self.value = Some(v);
89//                v
90//            },
91//        }
92//    }
93//}
94
95// 第二阶段:只针对所有u32类型参数有效
96struct Cacher<T>
97    where T: Fn(u32) -> u32
98{
99    calculation: T,
100    value: HashMap<u32, Option<u32>>,
101}
102
103impl<T> Cacher<T> where T: Fn(u32) -> u32 {
104    fn new(calculation: T) -> Cacher<T> {
105        Cacher {calculation, value: HashMap::new()}
106    }
107
108    fn value(&mut self, arg: u32) -> u32 {
109        let &opt = self.value.get(&arg).unwrap_or(&None);
110        match opt {
111            Some(v) => v,
112            None => {
113                let v = (self.calculation)(arg);
114                self.value.insert(arg, Some(v));
115                v
116            },
117        }
118    }
119}
120
121// 第三阶段:只针对所有参数类型参数有效 TODO: 实现有问题
122//struct Cacher<T, N>
123//    where T: Fn(N) -> u32
124//{
125//    calculation: T,
126//    value: HashMap<N, Option<u32>>,
127//}
128//
129//impl<T, N> Cacher<T, N>
130//    where
131//        T: Fn(N) -> u32,
132//        N: cmp::Eq + hash::Hash
133//{
134//    fn new(calculation: T) -> Cacher<T, N> {
135//        Cacher {calculation, value: HashMap::new()}
136//    }
137//
138//    fn value(&mut self, arg: N) -> u32 {
139//        let &opt = self.value.get(&arg).unwrap_or(&None);
140//        match opt {
141//            Some(v) => v,
142//            None => {
143//                let v = (self.calculation)(arg);
144//                self.value.insert(arg, Some(v));
145//                v
146//            },
147//        }
148//    }
149//}
150
151#[test]
152fn call_with_different_values() {
153    let mut c = Cacher::new(|a| a);
154
155    let v1 = c.value(1);
156    let v2 = c.value(2);
157
158    assert_eq!(v2, 2);
159}