可以安全地忽略宏和内置之间的区别吗?

时间:2011-02-25 17:53:54

标签: macros clojure lisp

我开始使用Clojure,这也是我的第一个口齿不清。显然有很多东西需要考虑,为了减轻认知负担,我试图找到我可以放心忽略的部分(现在)。

可以安全地处理带有内置插件的宏和表单相同的表单,还是会出现以后会出现的陷阱?

换句话说,我是否会遇到需要知道(defn f1 [])扩展到

的情况
(def f1 (.withMeta (clojure.core/fn f1 ([])) (.meta (var f1))))

3 个答案:

答案 0 :(得分:9)

一般来说,宏的构成方式非常不同。宏不是“一等公民”:你不能将它们传递给map等,你不能将它们存储在变量中,你不能将它们apply变成一个参数列表。最初你不需要担心这些,因为它们显然不起作用:一个微妙的,难以检测的错误会更令人不安。如果你试图运行

(map if [true false true false] [1 2 3 4] [-1 -2 -3 -4])

if 不是函数的事实将变得非常明显。请记住,宏不是函数,你应该没问题:)

PS:宏是(fn (fn (fn :-D) :^P) :O)

答案 1 :(得分:7)

几乎在所有情况下,您都可以完全忽略这种区别。 (实际上你有,因为fn不是内置的 - 它是一个扩展到fn *的宏)

我遇到的唯一例外是,如果您尝试重新定义它们,宏和内置函数的行为会有所不同。只是不要重新定义任何现有的功能,你可以很好地对待它们。

答案 2 :(得分:1)

我自己就是一个Clojure新手,但还有一点时间尝试这种语言。

我可以说Clojure内置宏非常安全,因为你可以在不知道它们是宏的情况下使用它们。

特别是,因为Clojure比Common Lisp更注重不变性,所以你很难陷入由行为不端的宏引起的错误。

所以,不,你不会遇到需要了解内置宏内部的情况。但是如果你想弄清楚你自己的自定义宏的内部,那么总是macroexpand