1use std::cmp::Eq;
6use std::hash::Hash;
7use std::collections::HashMap;
8
9pub struct CachedFunction<TFunction, TInput, TReturn>
12where
13 TFunction : Fn(TInput) -> TReturn,
14 TInput : Eq + Hash + Copy,
15 TReturn: Copy
16{
17 calculation: TFunction,
18 values: HashMap<TInput, TReturn>
19}
20
21impl<TFunction, TInput, TReturn> CachedFunction<TFunction, TInput, TReturn>
22where
23 TFunction : Fn(TInput) -> TReturn,
24 TInput : Eq + Hash + Copy,
25 TReturn: Copy
26{
27 pub fn new(function: TFunction) -> CachedFunction<TFunction, TInput, TReturn> {
46 CachedFunction {
47 calculation: function,
48 values: HashMap::new()
49 }
50 }
51
52 pub fn value(&mut self, arg: TInput) -> TReturn {
60 if self.values.contains_key(&arg) {
61 self.values[&arg]
62 }
63 else {
64 let value = (self.calculation)(arg);
65 self.values.insert(arg, value);
66 value
67 }
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn cached_function_value_returns_expected_value() {
77 let input = 4;
78 let closure = |x: i32| x * x;
79 let expected = closure(input);
80 let mut function = CachedFunction::new(closure);
81
82 let actual = function.value(input);
83
84 assert_eq!(expected, actual);
85 }
86
87 #[test]
88 fn cached_function_returns_expected_value_on_subsequent_calls() {
89 let input = 4;
90 let mut function = CachedFunction::new(|x: i32| x * x);
91 let expected = function.value(input);
92 let actual = function.value(input);
93
94 assert_eq!(expected, actual);
95 }
96}