Comparative Macrology (2014)
&gt; Macros in CL are just functions that run at compile time<p>Macros work fine in a Common Lisp interpreter at runtime.<p>Here we use an interpreter:<p>Define a macro, which prints a message when it is running.<p><pre><code>    CL-USER 13 &gt; (defmacro swap (x y)
                  (print &#x27;(&gt; running the swap macro function))
                  (let ((tmp-sym (gensym)))
                    `(let ((,tmp-sym ,x))
                       (setf ,x ,y)
                       (setf ,y ,tmp-sym))))
    SWAP
</code></pre>
Use it:<p><pre><code>    CL-USER 14 &gt; (defun foo (a b)
                  (let ((a1 a)
                        (b1 b))
                    (print (list a1 b1))
                    (swap a1 b1)
                    (print (list a1 b1))
                    (values)))
    FOO
</code></pre>
The macro function wasn&#x27;t running, otherwise we had it print something.<p>Run the code. The macro is run, too.<p><pre><code>    CL-USER 15 &gt; (foo 20 30)

    (20 30) 
    (&gt; RUNNING THE SWAP MACRO FUNCTION) 
    (30 20) 
</code></pre>
Run the code again. The macro is run, too.<p><pre><code>    CL-USER 16 &gt; (foo 10 40)

    (10 40) 
    (&gt; RUNNING THE SWAP MACRO FUNCTION) 
    (40 10) 
</code></pre>
Compile the code, the macro now runs, too.<p><pre><code>    CL-USER 17 &gt; (compile &#x27;foo)

    (&gt; RUNNING THE SWAP MACRO FUNCTION) 
    FOO
    NIL
    NIL
</code></pre>
In compiled code the macro is no longer needed to run:<p><pre><code>    CL-USER 18 &gt; (foo 10 40)

    (10 40) 
    (40 10) 
</code></pre>
Note also what pkhuong said, the SWAP macro will run the place forms twice.<p>Additionally it&#x27;s possible to observe the change:<p><pre><code>    CL-USER 25 &gt; (let ((a (vector 10))
                       (b (vector 20)))
                   (swap (aref a (progn (print (list :a a)) 0))
                         (aref b (progn (print (list :b a)) 0)))
                   (values a b))

    (:A #(10)) 
    (:A #(10)) 
    (:B #(10)) 
    (:B #(20))   ; &lt;- here a is already changed when we get the place value for b
    #(20)
    #(10)

</code></pre>
Common Lisp has a built-in ROTATEF, which takes care of that and which we can use as a replacement for SWAP:<p><pre><code>    CL-USER 27 &gt; (let ((a (vector 10))
                       (b (vector 20)))
                   (rotatef (aref a (progn (print (list :a a)) 0))
                            (aref b (progn (print (list :b a)) 0)))
                   (values a b))

    (:A #(10))    ; &lt;- only once computed in the first subform to ROTATEF
    (:B #(10))    ; &lt;- only once computed in the second subform to ROTATEF
                  ; also the computation of the new value for B does not observe
                  ;  the new value of A

    #(20)
    #(10)
</code></pre>
Thus a &#x27;real&#x27; SWAP macro will need to look to be different from what the article presents. Otherwise it will not play nicely with the rest of the language: multiple evaluations and side effects are the problems to address.