
module caching;

import std.typecons;

template cached(F : R function(P), R, P...) {
    R cached(P p) {
        static R[Tuple!(P)] cache = [];
        R* pointer = Tuple!(P)(p) in cache;
        if(pointer !is null) {
            return *pointer;
        } else {
            cache[Tuple!(P)(p)] = F(p);
            return cache[Tuple!(P)(p)];
        }
    }
}

pure int fib(int n) {
    if(n<2) return n;
    return fib(n-1) + fib(n-2);
}

pure int cfib_impl(int n){
    if(n<2) return n;
    return cfib(n-1) + cfib(n-2);
}

alias cached!cfib_impl cfib;

void main() {
    writeln("Running fib()");
    fib(200);
    writeln("Running cfib()");
    cfib(200);
    writeln("Finished!");
}