+
+/// Wrap and cache an expensive calculation
+///
+/// This calls a closure just once for every distinct argument. Any subsequent
+/// call to `.value()` with the same argument uses the cached value.
+pub struct Cacher<T, A, V>
+where
+ T: Fn(A) -> V,
+ A: Eq + Copy + std::hash::Hash,
+ V: Copy,
+{
+ calc: T,
+ values: HashMap<A, V>,
+}
+
+impl<T, A, V> Cacher<T, A, V>
+where
+ T: Fn(A) -> V,
+ A: Eq + Copy + std::hash::Hash,
+ V: Copy,
+{
+ pub fn new(calc: T) -> Cacher<T, A, V> {
+ Cacher { calc, values: HashMap::new() }
+ }
+
+ pub fn value(&mut self, arg: A) -> V {
+ match self.values.get(&arg) {
+ Some(v) => *v,
+ None => {
+ let v = (self.calc)(arg);
+ self.values.insert(arg, v);
+ v
+ }
+ }
+ }
+}