Revisions for ⁨cacher fixed⁩

View the changes made to this paste.

unlisted ⁨1⁩ ⁨file⁩ 2019-07-31 13:46:34 UTC

cacher.rs

@@ -0,0 +1,95 @@

+use std::thread;
+use std::time::Duration;
+use std::collections::HashMap;
+
+struct Cacher<T, P, R>
+    where T: Fn(&P) -> R,
+          P: std::cmp::Eq + std::hash::Hash
+{
+    calculation: T,
+    values: HashMap<P, R>,
+}
+
+impl<T, P, R> Cacher<T, P, R>
+    where T: Fn(&P) -> R,
+          P: std::cmp::Eq + std::hash::Hash
+{
+    fn new(calculation: T) -> Cacher<T, P, R> {
+        Cacher {
+            calculation,
+            values: HashMap::new(),
+        }
+    }
+
+    fn value(&mut self, arg: P) -> &R {
+        use std::collections::hash_map::Entry;
+        match self.values.entry(arg) {
+            Entry::Occupied(entry) => entry.into_mut(),
+            Entry::Vacant(entry) => {
+                let v = (self.calculation)(entry.key());
+                entry.insert(v)
+            }
+        }
+    }
+}
+
+fn generate_workout(intensity: u32, random_number: u32) {
+    let mut expensive_result = Cacher::new(|num| {
+        println!("calculating...");
+        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)
+            );
+        }
+    }
+}
+
+fn main() {
+    let simulated_user_specified_value = 10;
+    let simulated_random_number = 7;
+
+    generate_workout(
+        simulated_user_specified_value,
+        simulated_random_number
+    );
+}
+
+#[cfg(test)]
+mod tests {
+    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 value_can_differ_return_type_from_parameter_type() {
+        let mut c = Cacher::new(|_a| String::from("hello"));
+
+        let v = c.value(5);
+        assert_eq!(*v, "hello");
+    }
+}