Macro ONCE-ONLY

Syntax:

once-only (name*) body-form*

Arguments and Values:

name---a symbol.

body-form---a form.

Description:

Meant to be used in macro code, once-only guards against multiple evaluation of its arguments in macroexpansion code.

once-only generates a Lisp form that evaluates each lexical variable named by the symbols given as name arguments to once-only, and evaluates the body forms in a lexical environment where these results are bound to their respective originating symbol.

That is, if the only name argument were the single 'alpha symbol, the body forms would be evaluated in a lexical environment where 'alpha is bound to the result of the evaluation of alpha in the lexical environment of the generated Lisp form.

Example:

With the following 3x macro:

(defmacro 3x (x)
  `(+ ,x ,x ,x))

These three forms evaluate to the same result because the form given as x argument is referencially transparent (i.e. it yields the same result each time it's evaluated):

(3x 2) === 6
(3x (1+ 1)) === 6
(let ((a 1)) (3x (1+ a))) === 6

But the following form has an argument that has side-effects and has different results for each of the three times it will be evaluated:

(let ((a 1)) (3x (incf a))) === 9

The problem is solved by protecting the body of the macro with once-only:

(defmacro 3x (x)
  (once-only (x)
    `(+ ,x ,x ,x)))

(let ((a 1)) (3x (incf a))) === 6

Manual Index