Generic Memoization
Tutorial Video
Text description (accessibility)
This video demonstrates the "Generic Memoization" functional Rust example. Difficulty level: Advanced. Key concepts covered: Functional Programming. Recursive functions with overlapping subproblems waste exponential time recomputing the same results. Key difference from OCaml: | Aspect | Rust | OCaml |
Tutorial
The Problem
Recursive functions with overlapping subproblems waste exponential time recomputing the same results. Memoization wraps a function with a cache: on the first call with given arguments, compute and store the result; on subsequent calls, return the cached value. While specific DP algorithms hard-code their memoization tables, generic memoization provides a reusable cache wrapper for any pure function. This pattern is fundamental in functional languages (Haskell's memoize, OCaml's Hashtbl-based wrappers) and enables transparent DP without restructuring code. Real-world uses: web request caching, computed property memoization in UI frameworks, and expensive query result caching.
🎯 Learning Outcomes
HashMap-backed memoizer that wraps any Fn(K) -> V where K is hashableRefCell<HashMap> for interior mutabilityCode Example
#![allow(clippy::all)]
//! PlaceholderKey Differences
| Aspect | Rust | OCaml |
|---|---|---|
| Interior mutability | RefCell<HashMap> | Hashtbl (inherently mutable) |
| Recursive wrapper | &Self second arg | ref to function |
| Key constraint | Eq + Hash + Clone | Hashtbl equality |
| Thread safety | Use Mutex<HashMap> instead | Not needed for single-threaded |
| Eviction | Manual HashMap::retain | Weak.t for GC integration |
| Lazy vs eager | Lazy (top-down) | Same |
OCaml Approach
OCaml memoization is simpler: let memoize f = let tbl = Hashtbl.create 16 in fun x -> match Hashtbl.find_opt tbl x with Some v -> v | None -> let v = f x in Hashtbl.add tbl x v; v. Recursive memoization uses a ref for the function: let rec_memo f = let r = ref (fun _ -> assert false) in let m = memoize (fun x -> f !r x) in r := m; m. OCaml's first-class mutability makes this straightforward. The Weak.t module enables cache eviction for memory-constrained situations.
Full Source
#![allow(clippy::all)]
//! PlaceholderDeep Comparison
OCaml vs Rust: Memoization Generic
Overview
See the example.rs and example.ml files for detailed implementations.
Key Differences
| Aspect | OCaml | Rust |
|---|---|---|
| Type system | Hindley-Milner | Ownership + traits |
| Memory | GC | Zero-cost abstractions |
| Mutability | Explicit ref | mut keyword |
| Error handling | Option/Result | Result<T, E> |
See README.md for detailed comparison.
Exercises
Arc<Mutex<HashMap>> and measure the synchronization overhead.memoize_recursive that allows the function to call itself via the memoized wrapper without &Self threading.