2012-08-30 18 views
7

我一直在寻找的源defmacro它使用“让”,在它的定义:在clojure中defmacro如何根据自身来定义?

(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] 

然而,“让”被定义为一个宏本身:

(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) [email protected])) 

有人能解释一下这是有效的,因为我无法理解如何根据需要“defmacro”的事物来定义“defmacro”。 (如果这是有道理的:)

回答

5

recusrive宏工作正常,并发生在clojure语言核心和其他程序中的许多地方。 宏只是返回S-Expressions的函数,所以它们可以像函数一样递归。在你的例子中,在let的情况下,它实际上是计算let*这是一个不同的函数(它可以在函数名中包含*),所以虽然递归宏很好,但这并不是一个例子

+2

不是关于明显的循环定义的问题吗? – Jeremy

8

这是可能的,因为在core.clj中定义defmacro函数之前已经有let的定义this location(稍后重新定义)。宏只是普通函数,它们绑定的变量的元数据键:macro的值为true,因此在编译时编译器可以区分宏(在编译时执行)和函数,没有这个元键就没有区分宏和函数的方法,因为宏本身是处理S表达式的函数。

+0

让你指出也依赖于自己定义 – Zubair

+2

不能:'(fn * let [&form&env&decl](cons'let * decl))'..它依赖于let?它定义了let函数。它使用了已经在clojure的java代码中定义的let * – Ankur

相关问题