I have been trying to do memorisation in Julia for the Fibonacci function. This is what I came up with.
The original unmodified code (for control purposes)
function fib(x)
if x < 3
return 1
else
return fib(x-2) + fib(x-1)
end
end
This is my first attempt
memory=Dict()
function memfib(x)
global memory
if haskey(memory,x)
return memory[x]
else
if x < 3
return memory[x] = 1
else
return memory[x] = memfib(x-2) + memfib(x-1)
end
end
end
My second attempt
memory=Dict()
function membetafib(x)
global memory
return haskey(memory,x) ? memory[x] : x < 3 ? memory[x]=1 : memory[x] = membetafib(x-2) + membetafib(x-1)
end
My third attempt
memory=Dict()
function memgammafib!(memory,x)
return haskey(memory,x) ? memory[x] : x < 3 ? memory[x]=1 : memory[x] = memgammafib!(memory,x-2) + memgammafib!(memory,x-1)
end
Are there other ways of doing so that I am not aware of?
The simplest way to do it is to use
get!
Note the
const
specifier outsidefibmem
. This avoids the need forglobal
, and will make the code faster as it allows the compiler to use type inference withinfib
.As pointed out in the comments, the Memoize.jl package is certainly the easiest option. This requires you to mark the method at definition time.
By far the most powerful approach, however, is to use Cassette.jl, which lets you add memoization to pre-existing functions, e.g.
A little bit of a description of what is going on:
MemoizeCtx
is the Cassette "context" which we are definingoverdub
is run instead of the original function definitionrecurse(...)
tells Cassette to call the function, but ignore the top leveloverload
.Now we can run the function with memoization:
Now what's even cooler is that we can take an existing function which calls
fib
, and memoize the call tofib
inside that function:(Cassette is still pretty hard on the compiler, so this may take a while to run the first time, but will be fast after that).