(defun memoize (fn) ;; the value returned from this function is the memoized version (a closure) of the given function fn.
(let ((cache (make-hash-table :test #’equal))) ;; First it create the cache (which will be wrapped as the closure that gets returned)
#’(lambda (&rest args) ;; define the memoized function (note we just treat the arguments to the function as a lump
(multiple-value-bind (val win) (gethash args cache) ;; gethash returns multiple values: val is the value found and win is true if the key was found
;; can't rely on val being nul to indicate the key not being found as nul is a valid value
(if win ;; if the key is found in the cache...
val ;; ...return the cached value...
(setf (gethash args cache) ;; ...otherwise invoke the original function, store the returned value in the cache and return the value.
(apply fn args)))))))