『実践Common Lisp』8章 once-onlyマクロ

自分で考えて書いてみた。本に載っている例とは少しだけロジックが異なるが、同様に動作する。

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

ところでこの中の (,@(loop …)) となっている部分を、次のように ,(loop …) に置き換えると、

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

なぜか動作しなくなる(do-primesのコンパイルでエラー)。理由がよく分からない。with-gensyms は後者の形で動いているのに…。

Leave a Reply