cacher.rs
@@ -0,0 +1,81 @@
+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 {
+ self.values.entry(arg)
+ .or_insert((self.calculation)(arg))
+ }
+}
+
+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);
+ }
+}