7

定義に「let」を使用する 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]

ただし、「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」を定義する方法を理解できないため、誰かがこれがどのように機能するかを説明できますか。(それが理にかなっていれば:)

4

2 に答える 2

8

これが可能なdefmacroのは、core.cljで関数を定義する前にletこの場所に(後で再定義される)の定義がすでに存在するためです。マクロは単なる通常の関数であり、バインドされている変数には:macro値を持つメタデータキーがあるtrueため、コンパイル時にコンパイラは、このメタキーがないと、マクロ(コンパイル時に実行される)と関数を区別できます。マクロ自体はS式を処理するために発生する関数であるため、マクロと関数を区別します。

于 2012-08-31T04:43:45.573 に答える
5

再帰マクロは正常に機能し、clojure 言語コアと他のプログラムの両方の多くの場所で発生します。マクロは S-Expressions を返す単なる関数であるため、関数と同じように再帰的にすることができます。あなたの例の場合、let実際にlet*は別の関数である caling です (関数名に * を含めることは問題ありません)。そのため、再帰マクロは問題ありませんが、これはたまたまそれらの例ではありません

于 2012-08-31T00:24:33.383 に答える