我一直在寻找defmacro的来源,在其定义中使用“let”:
(def
^{:doc "Like defn, but the resulting function name is declared as a
macro and will be used as a macro by the compiler when it is
called."
:arglists '([name doc-string? attr-map? [params*] body]
[name doc-string? attr-map? ([params*] body)+ attr-map?])
:added "1.0"}
defmacro (fn [&form &env
name & args]
(let [prefix (loop [p (list name) args args]
但是,“let”被定义为宏本身:
(defmacro let
"binding => binding-form init-expr
Evaluates the exprs in a lexical context in which the symbols in
the binding-forms are bound to their respective init-exprs or parts
therein."
{:added "1.0", :special-form true, :forms '[(let [bindings*] exprs*)]}
[bindings & body]
(assert-args
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
`(let* ~(destructure bindings) ~@body))
有人可以解释这是如何工作的,因为我无法理解“defmacro”如何根据需要“defmacro”定义的事物来定义。 (如果这是有道理的:)
答案 0 :(得分:8)
这是可能的,因为在核心.clj中定义defmacro
函数之前,this location已经有了let
的定义(稍后会重新定义)。宏只是普通函数,它们绑定的var具有值:macro
的元数据键true
,因此在编译时编译器可以区分宏(在编译时执行)和函数没有这个元键,就没有办法区分宏和函数,因为宏本身就是一个碰巧处理S表达式的函数。
答案 1 :(得分:5)
recusrive宏工作得很好,并且在clojure语言核心和其他程序中的许多地方都会出现。 宏只是返回S-Expressions的函数,因此它们可以像函数一样递归。在你的例子中let
的情况下,它实际上正在调用let*
这是一个不同的函数(在函数名中有*很好),所以虽然递归宏很好,但这不会发生在是他们的一个例子