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
use std::thread;
use std::time::Duration;
use std::collections::HashMap;
pub struct Cacher<T, P, O>
where T: Fn(P) -> O,
P: std::cmp::Eq + std::hash::Hash + Copy,
O: Copy
{
pub caculation: T,
pub value: HashMap<P, O>,
}
impl<T, P, O> Cacher<T, P, O>
where T: Fn(P) -> O,
P: std::cmp::Eq + std::hash::Hash + Copy,
O: Copy
{
pub fn new(caculation: T) -> Cacher<T, P, O> {
Cacher {
caculation,
value: HashMap::new(),
}
}
pub fn value(&mut self, arg: P) -> O {
let ret = match self.value.get(&arg) {
Some(v) => *v,
None => {
let v = (self.caculation)(arg);
v
}
};
self.value.insert(arg, ret);
ret
}
}
pub fn generate_workout(intensity: u32, random_number: u32) {
let mut expensive_result = Cacher::new(|num| {
println!("calculating slowly...");
thread::sleep(Duration::from_secs(2));
num
});
if intensity < 25 {
println!(
"Today, do {} pushups!",
expensive_result.value(intensity)
);
println!(
"Next, do {} situps!",
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)
);
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[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);
}
#[test]
fn call_with_different_values_2() {
let mut c = Cacher::new(|mystring: &str| mystring.len());
let _v1 = c.value("abc");
let v2 = c.value("abcde");
assert_eq!(v2, 5);
}
}