2011-12-02 5 views
2

ポール・グラハムズの練習の1つANSI Common Lispの本は、次のとおりです。変数のリストとコード本体を取り、変数が元の値に戻っていることを確認するマクロを定義するコードの本体が評価された後マクロの引数のシンボル名を保存する

この演習で問題となっているのは、入力変数のシンボル名を保存する方法です。以下では、シンボルがバインドされている値のみを保存するところから始めます。

(defmacro save-run (varlist &body body) 
    `(let ((valuelist (list ,@varlist))) 
    (format t "valuelist: ~A" valuelist))) 

(let ((a 5)(b 6)) 
    (values '(a b)) 
    (save-run (a b) 
     (setf a 7) 
     (setf b 8))) 

[507]> valuelist: (5 6) 

編集:ここで、変数が保存され、復元されるソリューションです(以下のヒントを参考にしてください)。しかし、Vatineの答えのように変数をシャドーイングする方がおそらくもっとエレガントです。

(defmacro save-run (varlist &body body) 
    `(let ((valuelist (list ,@varlist))) 
    ,@body 
    (multiple-value-setq ,varlist (values-list valuelist)))) 
+0

'(progn、@ body)'は必要ありません。 '、@ body'と同じ効果があります。 – finnw

+0

'(multiple-value-setq、varlist ...)の代わりに'(setf(values、@ varlist)...) 'を使うと、変数のいくつかはシンボル以外の場所にすることができます。 '(save-run((cdr x))...)' – finnw

+0

あなたがここで何を意味するのか分かりません。私はドキュメントを見て、setfはリストではなく、ペアで割り当てられた偶数の引数しか取ることができません。 – snowape

答えて

3

シンボルのリストを取得するには、すべてを行う必要があるVARLISTの内容を引用している:

(defmacro save-run (varlist &body body) 
    `(let ((namelist ',varlist) 
     (valuelist (list ,@varlist))) 
    (format t "namelist: ~A~%" namelist) 
    (format t "valuelist: ~A~%" valuelist))) 

私は、これはしかし、最終defnitionに有用ではないだろうと思います。実行時にシンボルのリストでできることはあまりありません。代わりに、マクロ展開でリストを挿入するのに適した場所を探してください。

また、あなたの代わりにハードコーディングされた変数名VALUELISTGENSYMを使用する場合があります:

(defmacro save-run (varlist &body body) 
    (let ((valuelist (gensym))) 
    `(let ((,valuelist (list ,@varlist))) 
     ,@body 
     (setf (values ,@varlist) (values-list ,valuelist))))) 
+0

ニースは、引用符とカンマを組み合わせることができることを知らなかった。 – snowape

+0

申し訳ありませんが、* namelist *を使用しないでください。値リストが必要です。私の悪い。 – finnw

2

個人的に、私たちは保存したい変数のための別の結合層をご紹介したいです。

あなたはとてもこのような何かが動作する可能性がありvarlistに変数のリストを持っている:

(defmacro save-run (varlist &body body) 
    `(let ,(loop for var in varlist 
       collect (list var var)) 
    ,@body)) 
+0

私はそれを気に入っています。 – snowape

1

私は本当にVatineのアプローチが好きでした。以下は、同じコードに展開する実装ですが、ループマクロの代わりにmapcarを使用します:

(defmacro save-run (varlist &body body) 
    `(let ,(mapcar #'list varlist varlist) 
    ,@body)) 
関連する問題