Recherche…
Syntaxe
- Le
'
symbole utilisé dans l'exemple macroexpand est juste du sucre syntaxique pour laquote
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 unelist
avec les valeurs des paramètres fournis à la macroinfix
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 dex
est sortie lors du développement de la macro (au lieu de sortir le symbolex
) -
~@
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#
insidelet
etand#
insideif
obtiendra le même nom