変数のリストとコード本体を取り、コードの本体が実行された後に変数が元の値に戻ることを確認するマクロを作成しようとしています(Paul Graham's ANSI Common Lisp)。gensymシンボルのリスト内でマクロが評価されない
はしかし、私は私のgensym
は、私は一つの場所でそれを期待してではなく、他の同様のもの(ノートとして評価される理由については不明だ:私は運動へのよりよい解決策があると知っている私はちょうど把握したいですなぜ評価の違いか)。
ここlst
gensymははmapcar
に渡されたlambda
の内部のリストに評価された最初の定義です:
(defmacro exec-reset-vars-1 (vars body)
(let ((lst (gensym)))
`(let ((,lst ,(reduce #'(lambda (acc var) `(cons ,(symbol-value var) ,acc))
vars
:initial-value nil)))
,@body
,@(mapcar #'(lambda (var) `(setf ,var (car ,lst)))
vars))))
しかし、私はそれが期待通りに正確に動作しますが、それが正しい解決策ではありませんなぜなら、値をリセットしようとすると、私はいつもlst
の最初の要素をつかんでいるからです。私は本当に2つのリストをマップしたい。だから今私は書く:
(defmacro exec-reset-vars-2 (vars body)
(let ((lst (gensym)))
`(let ((,lst ,(reduce #'(lambda (acc var) `(cons ,(symbol-value var) ,acc))
vars
:initial-value nil)))
,@body
,@(mapcar #'(lambda (var val) `(setf ,var ,val))
vars
lst))))
しかし、今私は#:G3984
がリストではないというエラーが表示されます。私が(symbol-value lst)
に置き換えた場合、変数に値がないというエラーが表示されます。しかし、どうしてですか?なぜの内部の値がlambda
にありますが、引数がmapcar
に渡されないのはなぜですか?
ありがとうございます。私が正しく理解するために、どちらの場合も 'lst'はマクロ展開時に同じ値を持っています。違いは、最初のケースで '(car、lst)'が展開され、展開されたフォームがランタイム中に評価され、 'lst'がリストである点です。一方、第2引数では 'mapcar'への引数としてマクロ展開中に評価されています。これは正しいです? –
@UnixOne:いいえ。実行時には 'lst'はありませんが、マクロ展開時には' lst'の値だった名前の変数があります。 –