2011-11-30 11 views
5

lispに渡されたn番目の式を返し、その式だけを評価するマクロをlispに書き込もうとしています。例:Lispマクロが欲しないときに式を評価する

(let ((n 2)) 
    (nth-expr n (/ 1 0) (+ 1 2) (/ 1 0))) 

3を返す必要があります。エラーで除算しています。私のマクロ定義は次の通りです:

私は間違っていると思いますか?ありがとう。

EDIT:上記の部分で私を助けるため@Vsevolod Dyomkinへ

感謝。もう一つの問題があります。私がしようとすると

(let ((n 3) (x "win") (y "lose")) 
    (nth-expr n (princ x) (princ x) (princ y) (princ x))) 

私はエラーError: Attempt to take the value of the unbound variable 'Y'を得ています。

私の更新されたコードは次のようになります。あなたはこのようなqoute,expressionsに持って

(defmacro nth-expr (n &rest expressions) 
    (let ((i (gensym)) 
     (expr (gensym)) 
     (num (gensym))) 
    `(let ((,num (eval ,n))) 
     (do ((,i 1 (1+ ,i)) 
      (,expr ',expressions (cdr ,expr))) 
      ((= ,i ,num) (eval (car ,expr))))))) 
+1

マクロで 'eval'を呼び出すのはなぜですか? – leppie

+0

@leppieもし私がしなければ、それは(princ y)を返しますが、私はそれを評価したいと思います。 – Daniel

+1

その段階では「Y」は存在しません。あなたは何をしようとしているのですか? – leppie

答えて

1

(defmacro nth-expr (n &rest expressions) 
    (let ((i (gensym)) 
     (expr (gensym))) 
    `(do ((,i 1 (1+ ,i)) 
      (,expr ',expressions (cdr ,expr))) 
     ((= ,i ,n) (car ,expr))))) 

そうでなければ、何を買ってあげることはこれです - expressionsリストです次のように挿入されます:

CL-USER> (let ((n 2)) 
      (macroexpand-1 '(nth-expr n (/ 1 0) (+ 1 2) (/ 1 0)))) 
(DO ((#:G864 1 (1+ #:G864)) 
    (#:G865 ((/ 1 0) (+ 1 2) (/ 1 0)) (CDR #:G865))) 
    ((= #:G864 N) (CAR #:G865))) 
+0

ああ、それは役に立ちます。それでは、実際に '(+ 1 2)'を返すのではなく '(+ 1 2)'を評価するために 'eval'を投げなければならないと想像します。 – Daniel

+0

私は上記の質問をしました。あなたはそれを助けようとすることができると思いますか?ありがとう。 – Daniel

+0

あなたの目標を達成するための最も簡単な方法は、n番目の式だけを評価することです。 '(defmacro nth-expr(n&body expressions)(n番目の式))' –

5

主なものは次のとおりです拡張と一緒に。

作業コードはどのように見えるのですか?マクロの使用が拡大するコードですか?

このようなコードを作成するためのマクロを作成します。

マクロで提供されているコードを評価していないことを確認してください。

問題の簡単な拡張ターゲットは、CASEフォームです。

(case n 
    (0 (do-this)) 
    (1 (do-that)) 
    (2 (do-something-else))) 

今ではCASEフォームへ(nth-expr n (/ 1 0) (+ 1 2) (/ 1 0))を展開されるマクロを書くのは簡単でなければなりません...

4

あなたはここにevalを必要としないし、一覧に式を格納するには必要ありません。

適切な実装は以下の通りです:あなたの第二の例では、エラーがEVALがあなたの辞書的に結合NXY変数を見ることができないということです

(CASE N ((1) (/ 1 0)) ((2) (+ 1 2)) ((3) (/ 1 0))) 
0

:として

(defmacro nth-expr (n &rest expressions) 
    `(case ,n 
     ,@(loop for e in expressions 
       for n from 1 
       collect 
       `((,n) ,e)))) 

あなたの例では、拡大します。

EVALためCLHSから

現在動的環境ヌル字句環境形態を評価。

あなたはXYなどの特殊な宣言した場合、それは動作します:

(let ((n 3) (x "win") (y "lose")) 
    (declare (special x y)) 
    (nth-expr n (princ x) (princ x) (princ y) (princ x))) 

をしかし、これはまだSK-logicによって提案CASEソリューションほど良好ではありません。