1use std::thread;
2use std::time::Duration;
3
4struct Cacher<T>
5 where T: Fn(u32) -> u32
6{
7 calculation: T,
8 value: Option<u32>,
9}
10
11impl<T> Cacher<T>
12 where T: Fn(u32) -> u32
13{
14 fn new(calculation: T) -> Cacher<T> {
15 Cacher {
16 calculation,
17 value: None,
18 }
19 }
20
21 fn value(&mut self, arg: u32) -> u32 {
22 match self.value {
23 Some(v) => v,
24 None => {
25 let v = (self.calculation)(arg);
26 self.value = Some(v);
27 v
28 },
29 }
30 }
31}
32
33fn generate_workout(intensity: u32, random_number: u32) {
34 let mut expensive_result = Cacher::new(|num| {
35 println!("calculating slowly...");
36 thread::sleep(Duration::from_secs(2));
37 num
38 });
39
40 if intensity < 25 {
41 println!(
42 "Today, do {} pushups!",
43 expensive_result.value(intensity)
44 );
45 println!(
46 "Next, do {} situps!",
47 expensive_result.value(intensity)
48 );
49 } else {
50 if random_number == 3 {
51 println!("Take a break today! Remember to stay hydrated!");
52 } else {
53 println!(
54 "Today, run for {} minutes!",
55 expensive_result.value(intensity)
56 );
57 }
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 # [test]
68 # [ignore]
69 fn slow_cache() {
70 let simulated_user_specified_value = 10;
71 let simulated_random_number = 7;
72
73 generate_workout(
74 simulated_user_specified_value,
75 simulated_random_number
76 );
77 }
78
79 #[test]
80 fn call_with_different_values() {
81 let mut c = Cacher::new(|a| a);
82
83 let v1 = c.value(1);
84 let v2 = c.value(2);
85
86 assert_eq!(v2, 2);
87 }
88}
89