サーチ…


構文

  • マクロ展開の例で使用される'記号は、 quote演算子の単なる構文的な砂糖です。その代わりに(macroexpand (quote (infix 1 + 2)))を書くことができます。

備考

マクロは、コンパイル時、つまりread-eval-print-loopevalステップ中に実行される単なる関数です。

リーダーマクロは、コンパイル時ではなく、読み込み時に展開されるマクロの別の形式です。

マクロを定義するときのベストプラクティス。

  • alpha-renameing、マクロは展開バインディング名の競合が発生する可能性があるためです。バインディングの競合は、マクロを使用するときに解決するのが非常に直感的ではありません。このため、マクロがスコープにバインディングを追加するたびに、各シンボルの末尾に#を使用することが必須です。

シンプルインフィックスマクロ

Clojureは次のような接頭辞表記を使用します。演算子はそのオペランドの前にあります。

たとえば、2つの数値の単純な和は次のようになります。

(+ 1 2)
;; => 3

マクロを使用すると、Clojure言語をある程度操作することができます。たとえば、コードを中置表記(例: 1 + 2 )で書くマクロを実装することができます。

(defmacro infix [first-operand operator second-operand]
    "Converts an infix expression into a prefix expression"
    (list operator first-operand second-operand))

上のコードが何をしているかを解説しましょう:

  • defmacroは、マクロを定義するために使用する特別な形式です。
  • infixは定義しているマクロの名前です。
  • [first-operand operator second-operand]は、このマクロが呼び出されたときに受け取ることを期待するパラメータです。
  • (list operator first-operand second-operand)は、マクロの本体です。それは単純に、 infixマクロに提供されたパラメータの値を持つlistを作成し、それを返します。

defmacroは、他のClojureの構文と少し違って動作するため、 特別な形式です。そのパラメータはすぐには評価されません(マクロを呼び出すとき)。これは私達が次のようなものを書くことができるものです:

(infix 1 + 2)
;; => 3

infixマクロは、 1 + 2引数を(+ 1 2)に展開します。これは、評価できる有効なClojure形式です。

infixマクロの生成内容を確認したい場合は、 macroexpand演算子を使用できます。

(macroexpand '(infix 1 + 2))
;; => (+ 1 2)

macroexpandはその名前が暗示するようにマクロを展開します(この場合は1 + 2(+ 1 2)に変換するためにinfixマクロを使用します)が、マクロ展開の結果をClojureの通訳。

クォートとクォート解除の構文

標準ライブラリの例( core.clj:807 ):

(defmacro and
  "Evaluates exprs one at a time, from left to right. If a form
  returns logical false (nil or false), and returns that value and
  doesn't evaluate any of the other expressions, otherwise it returns
  the value of the last expr. (and) returns true."
  {:added "1.0"}
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))
  • `と呼ばれる構文の引用は次のようである(quote)再帰的な、しかし:それが引き起こす(let …)(if …)などであるようでないマクロ展開時にはなく、出力を評価します
  • ~別名にunquote構文引用符で囲まれた形の内部単一のフォームの構文引用符をキャンセルします。そうxマクロを展開したときの値が出力される(代わりに出力するx記号)
  • ~@ aka unquote-splicingはunquoteと似ていますが、list引数をとり、それを展開し、各リスト項目を別々の形式にします
  • #名前の競合を避けるために、シンボルに一意のIDを追加します。それはそう、構文引用符で囲まれた式の中に同じシンボルに同じIDを追加and#内部letand#内部のif 、同じ名前を取得します


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow