我刚开始学习Clojure,这也是我第一次接触Lisp语言。显然有很多需要掌握的知识点,为了减轻认知负担,我试图找出哪些部分可以暂时忽略。
对于宏表达式和内置表达式,我们可以安全地将它们视为同等重要吗?还是会遇到潜在的问题呢?
换句话说,我是否会遇到需要知道 (defn f1 [])
展开成什么形式的情况?
(def f1 (.withMeta (clojure.core/fn f1 ([])) (.meta (var f1))))
宏通常组合方式完全不同。宏不是“头等公民”:您不能将它们传递给map
等函数,也无法将其存储在变量中或将其应用于参数列表。最初您不需要担心这些问题,因为它们显然无法工作:一个微妙且难以检测的错误会带来更大的麻烦。如果您尝试运行它们,则会出现这样的错误。
(map if [true false true false] [1 2 3 4] [-1 -2 -3 -4])
如果if语句不是一个函数,这一点将非常明显。只需记住宏不是函数,你就会没问题 :)
PS: 宏是(fn (fn (fn :-D) :^P) :O)
在几乎所有情况下,您可以完全忽略这种区别。(实际上,您已经这样做了,因为fn也不是内置的,它是一个扩展到fn*的宏)
我遇到的唯一例外是,如果您尝试重新定义宏和内置函数,它们会有不同的行为。只要不重新定义任何现有功能,您就可以将它们视为相同。
我自己也是一个Clojure新手,但花了更多时间尝试这种语言。
我可以说Clojure内置的宏非常安全,因为你甚至可以在不知道它们是宏的情况下使用它们。
特别是因为Clojure比Common Lisp更注重不可变性,所以很难因为宏的错误行为而导致bug。
所以,不,你不会遇到需要了解内置宏内部工作原理的情况。但如果你想弄清楚自己定制宏的内部工作原理,总有macroexpand可以帮助你。