I'm trying to come up with an "elegant" way of calculating Fibonacci for number in Rust, using recursion and memoization (self-imposed requirements).
This is what I have so far:
fn fib(n: usize, memo: &mut [Option<usize>]) -> usize {
memo[n].map(|v| v).unwrap_or_else(|| {
let result = {
if n > 1 {
fib(n - 1, memo) + fib(n - 2, memo)
} else {
1
}
};
memo[n] = Some(result);
result
})
}
fn main() {
let number = 46;
let mut memo: Vec<Option<usize>> = vec![None; number + 1];
println!("{}", fib(number, &mut memo));
}
My cache in this implementation is just a slice of optional values, if the position contains Some(x)
that's a cache hit, otherwise, in a closure, compute the value, passing the cache along, and just before returning the value save it as a Some(v)
in the cache.
I figured that setting up a cache this way would make writes faster, since the memory is already allocated.
Can it be made faster? Or cleaner/more readable?
map()
isn't necessary. \$\endgroup\$std::num::NonZeroUsize
will save you space \$\endgroup\$map()
call is leftover code from a previous version of the code. Interestingly, Clippy completely overlooks the uselessmap()
. \$\endgroup\$map()
— there are actually times wheremap(|x| x)
isn't a no-op, surprisingly. \$\endgroup\$map(|x| x)
is useful or not? Or does it deserves a full question in StackOverflow? \$\endgroup\$