# Once-only macro

I have been learning common lisp and am a newbie, using the great book Practical Common Lisp. There is a once-only macro in the book that I spent a lot of time figuring out how it works. Even after I figured out how it works, I still have to look at it and think for a while every time I come across it.

I tried to write myself a new one, like this:

(defmacro my-once-only ((&rest names) &body body)
(let (,@ (loop for n in names collect (,n (eval ,n))))
,@body))

I don't use any gensyms; I just use the original name. They get shadowed by the value of the form they represent and the forms are evaluated only once. For now I can't see any problems in this implementation. Does it have any problems, like potential abstraction leak?

Here is the original once-only macro:

(defmacro once-only ((&rest names) &body body)
(let ((gensyms (loop for n in names collect (gensym))))
(let (,@(loop for g in gensyms collect (,g (gensym))))
(let (,,@(loop for g in gensyms for n in names collect (,,g ,,n)))
,(let (,@(loop for n in names for g in gensyms collect (,n ,g)))
,@body)))))

I tried to expand my own version

(macroexpand-1 '(my-once-only (start end)
(do ((x ,start (1+ x)))
((> x ,end))
(print x))))

It gives:

(LET ((START (EVAL START)) (END (EVAL END)))
(DO ((X ,START (1+ X))) ((> X ,END)) (PRINT X)))