数値nを取り、本体をn回評価する再帰的な Lisp マクロを作成しています(ANSI Lisp の演習)。私はこれを行うための 2 つの方法を試しました。展開時にマクロ自体を呼び出す方法と、マクロをローカル再帰関数に展開する方法です。どちらも私が望むようには機能しません。
これが最初のものです。スタック オーバーフローがありますが、macroexpand-1 を使用してその展開を見ると、問題ないように思えます。
(defmacro n-times (n &rest body)
(let ((i (gensym)))
`(let ((,i ,n))
(if (zerop ,i) nil
(progn
,@body
(n-times (- ,i 1) ,@body))))))
これが 2 番目のものです。「未定義の関数 #xxxx が引数 (z) で呼び出されました」というエラーが発生します。ここで #xxxx は gensym の名前で、z は呼び出した数値よりも 1 小さい値です。gensyms と flet を一緒に使用する方法に問題があると思いますが、これを正しく行う方法がわかりません。
(defmacro n-times (n &rest body)
(let ((g (gensym)))
`(flet ((,g (x)
(if (zerop x) nil
(progn
,@body
(,g (- x 1))))))
(,g ,n))))