defaultdict() and memoization
After the previous post, it came across me that member_missing can be used to implement something like Python’s defaultdict. So I thought it’s interesting to code up an example leveraging this ability.
You know the fibonacci calculating algorithm right? This is the fibonacci code (except written in Bike, not Java) that I use to teach my students about recursion in an entry Java programming course:
var fib = func(n) {
n < 2 ? 1 : fib(n-1) + fib(n-2)
};
Clean and simple! A base case on the left expression of the ternary and a recursive case on the right. Probably among the best to introduce people to the concept of recursion. What I didn't tell my students is that this is extremely inefficient. Pick fib(30) for example. It will invoke fib(29) + fib(28). fib(29) in turn invokes fib(28) + fib(27). Notice something? No? Read again? Still no? fib(28) is executed twice. And this is just the top part of the call tree. As you go down further, this phenomena is phenomenal, i.e. fib(27) is invoked tree times, fib(26) four times and so on! Needless to say, your CPU won't be very happy. Enter memoization.
In a nutshell, we use memoization as a technique to cache result of previous invocations. Assume the function has no side effect (i.e. being idempotent), which should generally be the case in a functional language, we can later reuse the cached result should the function is invoked again with the same arguments. Here's the code to compute fibonacci making use of memoization technique (and member_missing, as defaultdict).
func memoize(f) {
var cache = {
member_missing: func() { null }
};
return func recur(n) {
cache[n] || (cache[n] = f(recur, n));
};
}
var fib = func(n) {
n < 2 ? 1 : fib(n-1) + fib(n-2)
};
var m_fib = memoize(func(recur, n) {
n < 2 ? 1 : recur(n-1) + recur(n-2);
});
load 'stopwatch.bk';
var watch = Bike.Stopwatch.create( ).start( );
println('fib(20) = {0} (elapsed: {1}ms)', fib(20), watch.stop());
watch.reset().start();
println('m_fib(20) = {0} (elapsed: {1}ms)', m_fib(20), watch.stop());
Run the code and you should notice a significant difference between the run time of the normal fibonacci and one with memoization.


By BREAKSTS penny stock