Skip to content

Instantly share code, notes, and snippets.

@peaceman
Created August 10, 2020 17:03
Show Gist options
  • Save peaceman/db39609dce5c54d4c146c101ff30ef09 to your computer and use it in GitHub Desktop.
Save peaceman/db39609dce5c54d4c146c101ff30ef09 to your computer and use it in GitHub Desktop.
rust closure memoization
use std::collections::HashMap;
struct Cacher<T, U, V>
where
T: Fn(U) -> V,
U: std::cmp::Eq + std::hash::Hash + Copy,
V: Copy,
{
calculation: T,
value: HashMap<U, V>,
}
impl<T, U, V> Cacher<T, U, V>
where
T: Fn(U) -> V,
U: std::cmp::Eq + std::hash::Hash + Copy,
V: Copy,
{
fn new(calculation: T) -> Cacher<T, U, V> {
Cacher {
calculation,
value: HashMap::new(),
}
}
fn value(&mut self, arg: U) -> V {
match self.value.get(&arg) {
Some(v) => *v,
None => {
let v = (self.calculation)(arg);
self.value.insert(arg, v);
v
}
}
}
}
#[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 call_with_different_types() {
let mut c = Cacher::new(|a: &str| a.len());
let v1 = c.value("foo");
assert_eq!(v1, 3);
let v2 = c.value("lelcrap");
assert_eq!(v2, 7);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment