Cacher

unlisted ⁨1⁩ ⁨file⁩ 2019-07-30 17:47:23 UTC

main.rs

Raw
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 {
        match self.values.get(arg) {
            Some(v) => *v,
            None => {
                let v = (self.calculation)(arg);
                self.values.insert(*arg, v);
                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);
    }
}