Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 在clojure中,当使用递归实现宏时,如何进行代码模板化_Macros_Clojure - Fatal编程技术网

Macros 在clojure中,当使用递归实现宏时,如何进行代码模板化

Macros 在clojure中,当使用递归实现宏时,如何进行代码模板化,macros,clojure,Macros,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 (defmac

我试图实现一个宏,以递归方式将中缀列表转换为前缀列表。我遇到如下问题:

;;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]
问题在哪里?如何使用代码模板正确定义宏

另外,我把代码改成了这个,它还能用,为什么?有什么区别

(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)))))

在原始版本中,
(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)))))

这与将“if block”放入backquote的绑定范围有什么关系吗?非常感谢@amalloy-这确实为我提供了一种解决问题()的不那么复杂的方法,但我试图理解最后一个代码块中的确切步骤。在这种情况下递归工作正常吗?我以
形式传递(1+2+3),但它只返回前两个操作数的和。另外,我认为
seq?
是检查重复出现的
y
值是否是确定是否再次出现的有效形式,对吗?