Skip to content

Instantly share code, notes, and snippets.

@sonthonaxrk
Last active February 10, 2025 12:53
Show Gist options
  • Save sonthonaxrk/53a7c12fd831651d727488b29a100239 to your computer and use it in GitHub Desktop.
Save sonthonaxrk/53a7c12fd831651d727488b29a100239 to your computer and use it in GitHub Desktop.
/// This short test is intended to determine confidence fighting the rust borrow checker.
/// Software isn't perfect and Rust often makes it tricky to pass mutable values around
/// when the type signatures aren't perfectly designed.
/// Task:
/// - Part 1: Make this compile
/// - Part 2: Make the compute function to be more readable
/// - Part 3: Write a test that asserts the cache was hit.
/// Rules
/// - Type signatures of functions and structures may NOT be changed.
/// - Substitution of types with generics is allowed as they are effectively macros that generate concrete types.
/// - The cache must be populated at the end of iteration.
/// - For Part 1. The only part you may edit is the `fn next(&mut self)` function, as we don't want to change the signature of compute as it's used elsewhere extensively.
/// - For Part 2: Only edit the inside of `fn compute`.
/// - For Part 3: You make change the signature, but not the mutability of the parameters in the `fn compute` function.
use std::collections::HashMap;
#[derive(Default, Debug)]
pub struct ExpensiveComputationCache {
cache: HashMap<u64, u64>,
}
// Imagine this is used elsewhere in a lot of places.
fn compute(n: u64, cache: &mut Option<ExpensiveComputationCache>) -> u64 {
if let Some(cache) = cache {
println!("Cache hit for {n}");
if let Some(value) = cache.cache.get(&n) {
return *value
}
}
println!("Cache miss for {n}");
let result = (1..=n).product();
if let Some(cache) = cache {
cache.cache.insert(n, result);
}
result
}
pub struct ExpensiveComputationIterator<'a, I: Iterator<Item = u64>> {
iter: I,
computation_cache: &'a mut ExpensiveComputationCache
}
impl<'a, I: Iterator<Item = u64>> Iterator for ExpensiveComputationIterator<'a, I> {
type Item = (u64, u64);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|num| {
let result = compute(num, self.computation_cache);
(num, result)
})
}
}
fn main() {
let numbers = vec![5, 3, 7, 5, 3, 10, 5, 5].into_iter();
let mut cache = ExpensiveComputationCache::default();
let iter = ExpensiveComputationIterator {
iter: numbers,
computation_cache: &mut cache, // Initialize the cache
};
for (num, result) in iter {
println!("Factorial of {} is {}", num, result);
}
println!("{cache:?}");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment