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
Recursion clojure递归宏定义_Recursion_Clojure_Macros - Fatal编程技术网

Recursion clojure递归宏定义

Recursion clojure递归宏定义,recursion,clojure,macros,Recursion,Clojure,Macros,您好,我正在学习Clojure宏,我正在尝试编写一个宏,将中缀形式转换为前缀形式,如下所示:(9+(1*3))=>(+9(*13)) 但如果按以下方式定义宏,则效果良好: (defn infix [form] (list (second form) (first form) (nth form 2))) (defn r-infix-fn [form] (if (coll? form) (map r-infix-fn (infix form)) form)) (de

您好,我正在学习Clojure宏,我正在尝试编写一个宏,将中缀形式转换为前缀形式,如下所示:(9+(1*3))=>(+9(*13))

但如果按以下方式定义宏,则效果良好:

(defn infix [form]
  (list (second form) (first form) (nth form 2)))

(defn r-infix-fn [form]
  (if (coll? form)
    (map r-infix-fn (infix form))
    form))

(defmacro r-infix [form]
  (r-infix-fn form))

(r-infix (9 + (1 * 2)));;=>11

我在调试第一个示例时遇到了一些困难,有人能帮我吗?

Clojure中的宏不是“一流公民”,这意味着它们不能以数据和函数(不是宏)可以使用的所有方式使用

无法映射宏:-(

因此,第一个示例尝试将宏传递给函数,这会导致无法获取宏值的错误。为了探究原因,让我们与足够高级的编译器进行一次虚拟对话

你好,编译器,请用这个宏来转换所有这些表达式

足够高级的编译器:我试图查看您的宏,当我阅读它时,它试图计算,我不确定您想要什么 如果我要传递给这个函数,宏在我读取时会消失

我:哦,对不起,我只是想要一个列表,然后改变它

足够高级的编译器:听起来像函数:-)

宏是用特殊标志标记的函数,该标志使它们在读取时运行,并在最终代码准备运行之前完全完成。这使得在编写编译器时,将它们传递给其他本身不是宏的东西变得非常混乱

其效果是一种称为宏传染的常见反模式,其中代码作为宏编写,只是因为它需要以某种动态方式调用另一个宏。结果,更多的代码被写成宏,这是一个向下的螺旋

第二种方法显示了正确的方法,其中宏的所有工作都是在普通函数(恰好由宏调用)中完成的,这些函数作为入口点包装在一个薄宏层中。当稍后有人需要将r-inflix-fn应用于其他东西时,可能是树,那么他们就不必为了调用您的宏而将新代码变成宏


一般来说,明智的做法是怀疑任何只能通过宏访问的代码。

潜在相关:似乎是一个几乎完全相同的“异地复制”:答案很好,但它忽略了一些重要内容:第一个示例不会导致“宏值”错误;事实上,它确实导致了一个arity异常。你能解释一下吗?@Carcigenicate我想这是因为第一个例子不是通过它的var调用宏,而是通过它自身的本地别名:
(defmacro foo[]body)
扩展为类似
(def^:macro foo(fn foo[&form&env]body))
,它是“内部的”
foo
,由
fn
命名的一个,它被传递到
map
。它没有标记为宏(因为它是本地的),并且需要两个额外的“隐藏”参数,因此算术不匹配。@amalloy Mm,很有趣。当我在REPL中胡闹时,我想我试着给它3个参数。哦,好吧。
(defn infix [form]
  (list (second form) (first form) (nth form 2)))

(defn r-infix-fn [form]
  (if (coll? form)
    (map r-infix-fn (infix form))
    form))

(defmacro r-infix [form]
  (r-infix-fn form))

(r-infix (9 + (1 * 2)));;=>11