I am trying to learn Lisp from Peter Seibel's book "Practical Common Lisp". In chapter 8 : "Macros: Defining your own", I came across this once-only macro. At the bottom of that page, an implementation is given. Now that is a pretty complicated macro to understand for me, so I saw this question on stackoverflow and there are some good explanations there.
However, even if I (still) havent fully understood the macro, I understood its purpose. So I tried to write my own implementation of it :
(defmacro my-once-only ((&rest names) &body body)
(let
(
(gensyms (loop for n in names collect (gensym)))
)
`(list 'let
(list ,@(loop for n in names for g in gensyms collect `(list ',g ,n)))
(let
,(loop for n in names for g in gensyms collect `(,n ',g))
,@body))))
(Please forgive me if I am not following standard lisp conventions of indentation, I was trying to indent the code in a way so I can understand what goes where, since I am new to this)
I tested this macro much the same way as is described in that chapter I linked, ie. calling the function with arguments like (random 100) so that if they are evaluated twice, results will be wrong. I also expanded my macro (and the macro I used it in) via macroexpand/macroexpand-1 and that seems to be correct too.
So I was wondering if my implementation is correct ? or is there something I am missing (which is likely I think)...