How to write @memoize that works in both local and global scope

cstjean
Sat, 07 Nov 2020 10:11:24 +0000
General Usage

Let’s write a @memoize f(x) = ... macro in Julia. Glossing over gensyms etc. it can just macroexpand into

memo = Dict()
f(x) = get(memo, x) do ... end

At the global scope memo will be a slow global variable, so let’s instead macroexpand to:

const memo = Dict()
f(x) = get(memo, x) do ... end

But oops, Julia doesn’t like const in the local scope. This won’t work to memoize a local function. Alright, let’s try

let memo = Dict()
    f(x) = get(memo, x) do ... end
end

to make our Lisp fathers proud. But the funny rule here is that at the global scope, f’s name will be mangled to make it a local function unless it is prefixed with a module, like Main.f(x) = get(memo, x) do ... end. I could use @__MODULE__ to get that but, of course, it won’t work at the local scope.

It’s quite a frustrating situation. Memoize.jl uses eval in the macro code to get around it, which is evil in its own way. And Memoization.jl uses generated functions (!)

This shouldn’t be so hard! Did we all miss something obvious?

7 posts - 4 participants