memoize-form
A simpler need than memoizing the results of a function with arguments is that of memoizing the results of a form. The tricky thing here is to do it just inline in the code, without using a global variable or such.

;; (MEMOIZED form) memoizes the result of form from its first evaluation.
;; Use like this:
;;    (defun secret-password (...) ....... (memoized (random 1000)) ......)

(eval-when (compile load eval)
  (when (eval '(flet ((ltv () (load-time-value (cons nil nil)))) (eq (ltv) (ltv))))
    (pushnew :eval-uses-compiler *features*)))

(defmacro memoized (form) 
  `(LET ((MEMORY
           (IF #-eval-uses-compiler (EVAL-WHEN (EVAL) T) #+eval-uses-compiler NIL
             ',(cons nil nil)
             ;; Careful: Different expansions of MEMOIZED forms must yield
             ;; LOAD-TIME-VALUE forms that are not EQ, otherwise compile-file
             ;; will coalesce these LOAD-TIME-VALUE forms. Therefore here we
             ;; explicitly cons up the list and don't use backquote.
             ,(list 'LOAD-TIME-VALUE '(CONS NIL NIL)))))
     (UNLESS (CAR MEMORY)
       (SETF (CDR MEMORY) ,form)
       (SETF (CAR MEMORY) T))
     (CDR MEMORY)))

You should probably be using either DEFVAR, LOAD-TIME-VALUE, or fare-memoization:MEMOIZED-FUNCALL for local memoizations.


language extension