Suche…


Syntax

  • Das ' Symbol im macroexpand Beispiel verwendet wird , ist nur syntaktischer Zucker für das quote Operator. Sie hätten (macroexpand (quote (infix 1 + 2))) schreiben können.

Bemerkungen

Makros sind nur Funktionen, die zur Kompilierzeit ausgeführt werden, dh während des eval Schritts in einer Read-Eval-Print-Schleife .

Reader-Makros sind eine andere Form von Makros, die zur Lesezeit und nicht zur Kompilierzeit erweitert werden.

Best Practice beim Definieren eines Makros.

  • Alpha-Umbenennung, Da sich ein Konflikt mit dem Namen der Bindungsnamen für das Expandieren ergibt. Bindungskonflikte lassen sich bei Verwendung des Makros nicht sehr intuitiv lösen. Wenn ein Makro dem Gültigkeitsbereich eine Bindung hinzufügt, ist es daher obligatorisch, das # am Ende jedes Symbols zu verwenden.

Einfaches Infix-Makro

Clojure verwendet die Präfixnotation, dh: Der Operator steht vor seinen Operanden.

Eine einfache Summe aus zwei Zahlen wäre zum Beispiel:

(+ 1 2)
;; => 3

Mithilfe von Makros können Sie die Clojure-Sprache bis zu einem gewissen Grad bearbeiten. Sie könnten beispielsweise ein Makro implementieren, mit dem Sie Code in Infix-Notation schreiben können (z. B. 1 + 2 ):

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

Brechen wir auf, was der Code oben macht:

  • defmacro ist ein spezielles Formular, mit dem Sie ein Makro definieren.
  • infix ist der Name des Makros, das wir definieren.
  • [first-operand operator second-operand] sind die Parameter, die dieses Makro erwartet, wenn es aufgerufen wird.
  • (list operator first-operand second-operand) ist der Körper unseres Makros. Es erstellt einfach eine list mit den Werten der Parameter, die für das infix Makro bereitgestellt werden, und gibt diese zurück.

defmacro ist eine spezielle Form, da sie sich im Vergleich zu anderen Clojure-Konstrukten etwas anders verhält: Ihre Parameter werden nicht sofort ausgewertet (wenn wir das Makro aufrufen). Das erlaubt uns etwas zu schreiben:

(infix 1 + 2)
;; => 3

Das infix Makro erweitert die 1 + 2 Argumente in (+ 1 2) Dies ist eine gültige Clojure-Form, die ausgewertet werden kann.

Wenn Sie sehen möchten, was das infix Makro generiert, können Sie den macroexpand Operator verwenden:

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

macroexpand der Name impliziert, erweitert macroexpand das Makro (in diesem Fall wird das infix Makro verwendet, um 1 + 2 in (+ 1 2) umzuwandeln). Das Ergebnis der Makroerweiterung wird jedoch nicht von bewertet Clojures Dolmetscher

Zitieren und Aufheben von Anführungszeichen

Beispiel aus der Standardbibliothek ( 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#))))
  • ` aufgerufenes Syntax-Zitat ist wie (quote) , aber rekursiv: Es bewirkt (let …) , (if …) usw., dass es während der Makroerweiterung nicht ausgewertet wird, sondern wie es ausgegeben wird
  • ~ aka unquote bricht das Syntaxzitat für ein einzelnes Formular in einem Syntax-Anführungszeichen ab. Der x -Wert wird also beim Erweitern des Makros ausgegeben (anstatt das x Symbol auszugeben)
  • ~@ aka unquote-splicing ist wie unquote, nimmt aber Listenargumente auf und erweitert es, wobei jedes Listenelement in eine separate Form gebracht wird
  • # fügt den Symbolen eine eindeutige ID hinzu, um Namenskonflikte zu vermeiden. Es fügt die gleiche ID für dasselbe Symbol in einem Ausdruck mit Syntax-Anführungszeichen an, also and# in let und and# in if , if derselbe Name erhalten wird


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow