Clojure 宏 : When can a function not duplicate a macro's behaviour?

标签 clojure macros

我正在研究 clojure 宏,我发现我可以通过函数组合来复制很多宏行为。

线程宏就是一个很好的例子:

(defn add1 [n] (+ n 1))
(defn mult10 [n] (* n 10))

(defn threadline [arg]
  (-> arg
      add1
      mult10))

我可以使用管道等高阶函数轻松复制这一点:

(defn pipe [& fns]
  (reduce (fn [f g] (fn [arg] (g(f arg)))) fns))

(def pipeline
  (pipe
   #(+ % 1)
   #(* % 10)))

一定存在宏不能被函数替换的情况。我想知道是否有人对此类情况以及所涉及的重复出现的主题有一些很好的例子。

最佳答案

宏的一个重要优点是它们能够在编译时转换代码,而无需评估任何代码。宏在编译期间接收代码作为数据,但函数在运行时接收。宏允许您在某种意义上扩展编译器。

例如,Clojure 的 andor 被实现为扩展为嵌套 if 形式的递归宏。这允许对 and/or 的内部形式进行惰性评估,即如果第一个 or 形式为真,则将返回其值,并且不返回任何值的其他人将被评估。如果您将 and/or 编写为函数,则在检查其所有参数之前都会对其进行求值。

短路控制流在 pipe 函数示例中不是问题,但与 -> 相比,pipe 增加了相当大的运行时复杂性code> 简单地展开为嵌套形式。尝试将其实现为函数的更有趣的宏可能是 some->

I'm finding that a lot of macro behavior I can just replicate with function composition

如果您的函数适合它,您当然可以用 comp 来替换带有函数组合的简单线程宏,类似于其他函数式语言中的“point free”风格:#(-> % inc str) 在功能上等同于 (comp str inc)#(str (inc %))

通常建议尽可能选择函数,即使在编写宏时,您通常也可以将大部分“工作”外包给函数。

关于Clojure 宏 : When can a function not duplicate a macro's behaviour?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50779972/

相关文章:

clojure - 常见的 lisp 阅读器宏有哪些 Clojure 没有的优势?

functional-programming - Clojure元数据有哪些用途?

linux - Linux内核中的IS_ALIGNED宏是做什么的?

c - 这个宏是什么意思?

clojure - 在 Clojure 中使序列产生副作用

clojure - 在运行时从 clojure 确定文件脚本目录

vim - 清除所有当前定义的 vim 宏

c - 使用宏扩展从 C 函数返回 double

macros - 宏想在 clojure 中使用符号而不是字符串

dictionary - doseq 中的 assoc 字符串导致空映射