Skip to content

Instantly share code, notes, and snippets.

@smertelny
Created October 27, 2019 06:35
Show Gist options
  • Save smertelny/e51fecace3419a4c9da002406a3326e1 to your computer and use it in GitHub Desktop.
Save smertelny/e51fecace3419a4c9da002406a3326e1 to your computer and use it in GitHub Desktop.
Rust book Chapter 13. Casher with HashMap
use std::collections::HashMap;
use std::thread;
use std::time::Duration;
struct Casher<T, K, V>
where
T: Fn(K) -> V,
{
calculation: T,
value: HashMap<K, V>,
}
impl<T, K, V> Casher<T, K, V>
where
T: Fn(K) -> V,
K: std::cmp::Eq + std::hash::Hash + std::marker::Copy,
V: std::marker::Copy,
{
fn new(calculation: T) -> Casher<T, K, V> {
Casher {
calculation,
value: HashMap::new(),
}
}
fn value(&mut self, arg: K) -> V {
match self.value.get(&arg) {
Some(v) => *v,
None => {
let res = (self.calculation)(arg);
self.value.insert(arg, res);
res
}
}
}
}
fn generate_workout(intensity: u32, random_number: u32) {
let mut expensive_result = Casher::new(|num| {
println!("Slow calculations done...");
thread::sleep(Duration::from_secs(2));
num
});
if intensity < 25 {
println!("Today, do {} pushups", expensive_result.value(intensity));
println!("Next, {} situps", expensive_result.value(intensity));
} else if random_number == 3 {
println!("Take a brake today!");
} else {
println!(
"Today, run for {} minutes",
expensive_result.value(intensity)
);
}
}
fn main() {
let user_value = 10;
let random_number = 7;
generate_workout(user_value, random_number);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cacher_with_different_args() {
let mut cacher = Casher::new(|a| a);
let v1 = cacher.value(1);
let v2 = cacher.value(2);
assert_eq!(v1, 1);
assert_eq!(v2, 2);
}
#[test]
fn cacher_with_different_closure_args() {
let mut c = Casher::new(|s| s);
let v1 = c.value("asd");
let v2 = c.value("qwe");
assert_eq!(v1, "asd");
assert_eq!(v2, "qwe");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment