Ricerca…


Sintassi

  • Il ' simbolo usato nell'esempio macroexpand è solo zucchero sintattico per l'operatore quote . Potresti aver scritto (macroexpand (quote (infix 1 + 2))) invece.

Osservazioni

Le macro sono solo funzioni che vengono eseguite in fase di compilazione, ovvero durante la fase di eval in un ciclo di lettura-eval-print .

Le macro di Reader sono un'altra forma di macro che viene espansa in fase di lettura piuttosto che in fase di compilazione.

Best practice durante la definizione della macro.

  • alpha-renaming, poiché la macro è espandibile potrebbe sorgere conflitto di nomi di binding. Il conflitto vincolante non è molto intuitivo da risolvere quando si utilizza la macro. Questo è il motivo per cui, ogni volta che una macro aggiunge un'associazione all'ambito, è obbligatorio utilizzare il simbolo # alla fine di ogni simbolo.

Macro Infix semplice

Clojure usa la notazione del prefisso, ovvero: L'operatore viene prima dei suoi operandi.

Ad esempio, una semplice somma di due numeri sarebbe:

(+ 1 2)
;; => 3

I macro ti consentono di manipolare la lingua Clojure in una certa misura. Ad esempio, è possibile implementare una macro che consente di scrivere codice in notazione infisso (ad es. 1 + 2 ):

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

Analizziamo il codice sopra riportato:

  • defmacro è un modulo speciale che usi per definire una macro.
  • infix è il nome della macro che stiamo definendo.
  • [first-operand operator second-operand] sono i parametri che questa macro si aspetta di ricevere quando viene chiamata.
  • (list operator first-operand second-operand) è il corpo della nostra macro. Crea semplicemente una list con i valori dei parametri forniti alla macro infix e restituisce quello.

defmacro è una forma speciale perché si comporta in modo leggermente diverso rispetto ad altri costrutti Clojure: i suoi parametri non vengono immediatamente valutati (quando chiamiamo la macro). Questo è ciò che ci permette di scrivere qualcosa come:

(infix 1 + 2)
;; => 3

La macro infix espanderà gli argomenti 1 + 2 in (+ 1 2) , che è un modulo Clojure valido che può essere valutato.

Se vuoi vedere che cosa genera la macro infix , puoi usare l'operatore macroexpand :

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

macroexpand , come implicito nel nome, espanderà la macro (in questo caso, utilizzerà la macro infix per trasformare 1 + 2 in (+ 1 2) ) ma non consentirà di valutare il risultato dell'espansione macro Interprete di Clojure.

Sintassi quoting e unquotation

Esempio dalla libreria standard ( 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#))))
  • ` called syntax-quote è come (quote) , ma ricorsivo: causa (let …) , (if …) , ecc per non valutare durante l'espansione della macro ma per produrre come è
  • ~ aka unquote annulla la sintassi-citazione per un modulo singolo all'interno di un modulo basato sulla sintassi. Quindi il valore di x viene emesso quando si espande la macro (invece di emettere il simbolo x )
  • ~@ alias unquote-splicing è come unquote ma prende l'argomento list e lo espande, ogni elemento dell'elenco in forma separata
  • # aggiunge un ID univoco ai simboli per prevenire conflitti di nome. Aggiunge lo stesso id per lo stesso simbolo all'interno dell'espressione con sintassi, così and# inside let e and# inside if otterrà lo stesso nome


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow