Buscar..


Sintaxis

  • El símbolo ' usado en el ejemplo de macroexpand es solo azúcar sintáctica para el operador de quote . Podría haber escrito (macroexpand (quote (infix 1 + 2))) lugar.

Observaciones

Las macros son solo funciones que se ejecutan en tiempo de compilación, es decir, durante el paso de eval en un ciclo de lectura-eval-print .

Las macros del lector son otra forma de macro que se expande en el momento de la lectura, en lugar del tiempo de compilación.

Mejores prácticas a la hora de definir macro.

  • alfa-cambio de nombre, ya que la macro es expandir enlace podría surgir un conflicto. El conflicto de enlace no es muy intuitivo de resolver cuando se utiliza la macro. Esta es la razón por la cual, cuando una macro agrega un enlace al alcance, es obligatorio usar el # al final de cada símbolo.

Macro Infix simple

Clojure usa la notación de prefijo, es decir: el operador aparece antes que sus operandos.

Por ejemplo, una suma simple de dos números sería:

(+ 1 2)
;; => 3

Las macros te permiten manipular el lenguaje de Clojure hasta cierto punto. Por ejemplo, podría implementar una macro que le permita escribir código en notación de infijo (por ejemplo, 1 + 2 ):

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

Vamos a desglosar lo que hace el código anterior:

  • defmacro es una forma especial que se utiliza para definir una macro.
  • infix es el nombre de la macro que estamos definiendo.
  • [first-operand operator second-operand] son los parámetros que esta macro espera recibir cuando se llama.
  • (list operator first-operand second-operand) es el cuerpo de nuestra macro. Simplemente crea una list con los valores de los parámetros proporcionados a la macro infix y los devuelve.

defmacro es una forma especial porque se comporta de manera un poco diferente en comparación con otras construcciones de Clojure: sus parámetros no se evalúan de inmediato (cuando llamamos a la macro). Esto es lo que nos permite escribir algo como:

(infix 1 + 2)
;; => 3

La macro infix expandirá los argumentos 1 + 2 a (+ 1 2) , que es una forma de Clojure válida que puede ser evaluada.

Si desea ver lo que genera la macro infix , puede usar el operador de macroexpand :

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

macroexpand , como lo macroexpand su nombre, expandirá la macro (en este caso, usará la macro infix para transformar 1 + 2 en (+ 1 2) ) pero no permitirá que el resultado de la expansión de macro sea evaluado por Intérprete de clojure

Sintaxis citando y sin citar

Ejemplo de la biblioteca estándar ( 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#))))
  • ` llamado syntax-quote es como (quote) , pero recursivo: hace (let …) , (if …) , etc. no se evalúa durante la expansión de macros sino que se genera como está
  • ~ aka unquote cancela syntax-quote para una sola forma dentro de la forma sintaxis entre comillas. Entonces, el valor de x se genera al expandir la macro (en lugar de mostrar el símbolo x )
  • ~@ aka unquote-splicing es como unquote pero toma el argumento de la lista y lo expande, cada elemento de la lista se forma de forma separada
  • # agrega una identificación única a los símbolos para evitar conflictos de nombre. Agrega la misma ID para el mismo símbolo dentro de la expresión entre comillas de sintaxis, por lo que and# dentro de let y and# inside if obtendremos el mismo nombre


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow