Use let-scoped cache

This solves multiple dispatch-related issues without leaking memory
when a memoized function is redefined, but only permits us to define
global functions.