2011-12-24 8 views
6

マクロを実装して、インフィックスリストを接頭辞1に再帰的に変換しようとしています。次のような問題が発生しました。clojureで、再帰を使用してマクロを実装するときにコードテンプレートを実行する方法

;;this works 
(defmacro recursive-infix [form] 
    (list (second form) (first form) 
     (if (not (seq? (nth form 2))) 
      (nth form 2) 
      (recursive-infix (nth form 2))))) 

;;this doesn't work 
(defmacro my-recursive-infix [form] 
    `(~(second form) ~(first form) 
     (if (not (seq? ~(nth form 2))) 
      ~(nth form 2) 
      (my-recursive-infix ~(nth form 2))))) 

(macroexpand '(recursive-infix (10 + 10))) 
;;get (+ 10 10) 

(macroexpand '(my-recursive-infix (10 + 10))) 
;;get (+ 10 (if (clojure.core/not (clojure.core/seq? 10)) 10 (user/my-recursive-infix 10))) 

(recursive-infix (10 + 10)) 
;;get 20 

(my-recursive-infix (10 + 10)) 
;;Don't know how to create ISeq from: java.lang.Integer [Thrown class java.lang.IllegalArgumentException] 

問題はどこですか?コードテンプレートでマクロを正しく定義するには?

P.S.私はこれにコードを変更し、それは動作します、なぜですか?違い?:オリジナル版で

(defmacro my-recursive-infix [form] 
    (if (not (seq? (nth form 2))) 
    `(~(second form) ~(first form) ~(nth form 2)) 
    `(~(second form) ~(first form) (my-recursive-infix (nth form 2))))) 
+0

それは「ブロック場合は、」パッティングを行うには何も持っていますバッククォートのバインディング範囲に? – lkahtz

答えて

13

何で、(if (not ...))チェックは、コンパイル時に起こっていました。あなたは代わりにそれを拡張コードに含めました。だから、あなたが望むように動かすことができる最小限の変更があります。それは事実上元のものと同じですが、引用されたものとそうでないものを「反転」させます。

(defmacro my-recursive-infix [form] 
    (let [third (nth form 2)] 
    `(~(second form) ~(first form) 
     ~(if (not (seq? third)) 
     third 
     `(my-recursive-infix ~third))))) 

しかし、それはむしろ、インプレースよりも、前もっての形の部分を引き出すために非構造を使用して少し立派です:

(defmacro my-recursive-infix [form] 
    (let [[x op y] form] 
    `(~op ~x ~(if (not (seq? y)) 
       y 
       `(my-recursive-infix ~y))))) 

、より良いまだ、本当に、移動することです外非再帰的な場合、(a)は、それは文字通りの数字のために働く、および(b)は、コードをよりそれがに展開するもののように見えるように:

(defmacro my-recursive-infix [form] 
    (if-not (seq? form) 
    form 
    (let [[x op y] form] 
     `(~op ~x (my-recursive-infix ~y))))) 
+0

非常に@amalloyありがとう - これは私に私の問題(https://stackoverflow.com/questions/41555991/mismatched-argument-count-to-recur-in-syntax-quoted-macro)を攻撃するために、私は最後のコードブロックの正確な手順を理解しようとしています。この場合、再帰は正しく機能していますか?私は(1 + 2 + 3)を 'form'として渡していますが、最初の2つのオペランドの和だけを返しています。また、 'seq? 'が再発した' y'値をチェックするのが正しいかどうかは、再発するかどうかを判断するための有効な形式ですか? – Ooberdan

関連する問題