I wrote code to (naively) perform automatic memoisation. I tried to write it in a functional programming style, and so did not make use of any global variables.

My Code

def naive_memoise(caches):
    def memoise(f):
        nonlocal caches
        def mem_f(n):
            nonlocal caches, f
            if f not in caches:
                caches[f] = {}
            if n not in caches[f]:
                caches[f][n] = f(n)
            return caches[f][n]
        return mem_f
    return memoise

Sample Usage

def fib(n):
    if n in [0, 1]:
        return n
    return  fib(n - 2) + fib(n - 1)

mem = naive_memoise({})
fib = mem(fib)
  • \$\begingroup\$ Is there any use case in which you would want to initialize the cache with something other than an empty dict? \$\endgroup\$ Commented Mar 3, 2019 at 19:05

1 Answer 1


This looks good to me and I have nothing important to add.

  • the nonlocal are not required here

  • in the code sample, you could use the @decorator syntax

  • maybe you could write something more generic than just functions taking a single parameter.

  • \$\begingroup\$ I could change the parameter of mem_f to *lst I guess so it could handle functions with multiple arguments. It would requires rewriting the functions that work with it though. Not sure I know a general way to do it without customising the functions to be memoised so they interface well with the memoisation closure. \$\endgroup\$ Commented Mar 2, 2019 at 23:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.