Recherche…


Syntaxe

  • Le ' symbole utilisé dans l'exemple macroexpand est juste du sucre syntaxique pour la quote opérateur. Vous pourriez avoir écrit (macroexpand (quote (infix 1 + 2))) place.

Remarques

Les macros ne sont que des fonctions qui s'exécutent au moment de la compilation, c'est-à-dire pendant l'étape d' eval dans une boucle read-eval-print-loop .

Les macros de lecteur sont une autre forme de macro qui est développée au moment de la lecture, plutôt que lors de la compilation.

Meilleure pratique lors de la définition de la macro.

  • Alpha-renaming, Puisque la macro est développée, le conflit de nom de liaison peut survenir. Le conflit de liaison n'est pas très intuitif à résoudre lors de l'utilisation de la macro. C'est pourquoi, chaque fois qu'une macro ajoute une liaison à la portée, il est obligatoire d'utiliser le # à la fin de chaque symbole.

Simple Infix Macro

Clojure utilise la notation préfixée, à savoir: l'opérateur vient avant ses opérandes.

Par exemple, une simple somme de deux nombres serait:

(+ 1 2)
;; => 3

Les macros vous permettent de manipuler le langage Clojure dans une certaine mesure. Par exemple, vous pouvez implémenter une macro qui vous permet d'écrire du code en notation infixe (par exemple, 1 + 2 ):

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

Décomposons ce que le code ci-dessus fait:

  • defmacro est un formulaire spécial que vous utilisez pour définir une macro.
  • infix est le nom de la macro que nous définissons.
  • [first-operand operator second-operand] sont les paramètres que cette macro s'attend à recevoir lorsqu'elle est appelée.
  • (list operator first-operand second-operand) est le corps de notre macro. Il crée simplement une list avec les valeurs des paramètres fournis à la macro infix et la retourne.

defmacro est une forme particulière car elle se comporte un peu différemment des autres constructions Clojure: ses paramètres ne sont pas immédiatement évalués (quand on appelle la macro). C'est ce qui nous permet d'écrire quelque chose comme:

(infix 1 + 2)
;; => 3

La macro infix étendra les arguments 1 + 2 dans (+ 1 2) , qui est un formulaire Clojure valide pouvant être évalué.

Si vous voulez voir ce que la macro infix génère, vous pouvez utiliser l'opérateur macroexpand :

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

macroexpand , implicite par son nom, développera la macro (dans ce cas, elle utilisera la macro infix pour transformer 1 + 2 en (+ 1 2) ) mais ne permettra pas d’évaluer le résultat de l’extension de la macro par L'interprète de Clojure.

Syntaxe entre guillemets

Exemple de la bibliothèque 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#))))
  • ` appelé syntaxe-citation est comme (quote) , mais récursif: il provoque (let …) , (if …) , etc. à ne pas évaluer lors de l'expansion de la macro mais à produire tel quel
  • ~ aka unquote annule les guillemets syntaxiques pour un formulaire unique dans une forme citée avec la syntaxe. Donc, la valeur de x est sortie lors du développement de la macro (au lieu de sortir le symbole x )
  • ~@ aka unquote-splicing est comme unquote mais prend un argument de liste et le développe, chaque élément de la liste se sépare
  • # ajoute un identifiant unique aux symboles pour éviter les conflits de noms. Il ajoute le même identifiant pour le même symbole à l'intérieur de l'expression citée entre syntaxes, and# inside let et and# inside if obtiendra le même nom


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow