2010-09-14 15 views
12

Estoy tratando de escribir un macro tutorial, y ahora necesito algunos ejemplos que son simples de entender, y sin embargo convincentes.Ejemplos simples pero convincentes de macros que ya no están en Clojure

El problema es que muchas de las cosas obvias ya están en clojure y contrib. Y creo que "mira, podemos volver a implementar todas las funciones de la biblioteca" podría no ser el mejor argumento para explicar por qué las macros son tan geniales.

¿Alguien ha recibido ejemplos bonitos (los de una línea son los mejores) que no les importaría que utilizara?

Aquí están las tres primeras partes del tutorial. En este momento es un poco vulgar, por lo que cualquier comentario sobre cómo podría mejorarse sería recibido con gratitud.

http://learnclojure.blogspot.com/2010/09/clojure-macro-tutorial-part-i-getting.html

http://learnclojure.blogspot.com/2010/09/clojure-macro-tutorial-part-ii-compiler.html

http://learnclojure.blogspot.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html

+2

Tal vez mi ejemplo favorito, que no estoy seguro es posible en clojure (tal vez un subconjunto limitado con CLJ-cont, pero completamente en el esquema), es la implementación de 'yield', como en Pitón, a través de' call/cc'. Es un ejemplo poderoso que realmente lleva a casa el hecho de que las macros pueden ayudarte a construir incluso los constructos más extravagantes en el lenguaje. – apg

Respuesta

4

me gustaría hablar más sobre los patrones: cuándo y cómo se una macro utiliza. por ejemplo ...

  • Protección de un recurso. Ejemplos: binding, with-open, ...
    (let [~x (get-resource)] (try [email protected] (finally (release-resource ~x))))
  • Definir cosas. Ejemplos: defn, defsnippet (enlive), defservice (anillo)
  • División de macro/controlador. Especialmente esta técnica quita mucho dolor macro. Me gusta la evaluación o captura múltiple. Ejemplo: with-bindings
  • Embellecer código feo. p.ej. cuando Taming multi-dim arrays
6

estoy trabajando en algún software de criptografía en clojure. Es muy divertido y el uso de pruebas unitarias lo hace más divertido porque no me pongo nervioso por romper las cosas. El problema es que todas las funciones de criptografía generan resultados diferentes en todo momento, ya que están impulsadas por un generador de números al azar bastante incorrecto.

¿Cómo se prueban las funciones aleatorias?

con un enlace macro por supuesto!

(defmacro with-fake-prng [ & exprs ] 
    "replaces the prng with one that produces consisten results" 
    `(binding [com.cryptovide.split/get-prng (fn [] (cycle [1 2 3])) 
      com.cryptovide.modmath/mody 719 
      com.cryptovide.modmath/field-size 10] 
     [email protected])) 

luego envuelvo mis funciones de prueba en (with-fake-prng (deftest mytest ....))

clojure tiene una gran cantidad de estos "macroes bind". como with-out-string y tal.

También tengo una macro que carga cada espacio de nombres en la réplica. (No utilizo esto mucho ahora que he cambiado a la torta)

(defmacro load-all [] 
    '(use 
    :reload-all 
    'com.cryptovide.modmath 
    ... 
    'com.cryptovide.gui 
    'com.cryptovide.checksum 
    'com.cryptovide.log)) 

PS: siempre importa la primera regla del club de macro

+0

¡Gran ejemplo! La alternativa es usar un marco de "inyección de dependencia", que es extremadamente feo en muchos casos. – apg

+0

A partir de Clojure 1.3, esto no funcionará más, ya que 'binding' solo puede redefinir mapeos para Vars declarado dinámico (que probablemente sus funciones no sean). En cambio, ahora deberíamos usar la macro predefinida 'with-redefs': http://clojuredocs.org/clojure_core/clojure.core/with-redefs. Sin embargo, el punto más importante es: este es un gran ejemplo del poder de las macros. Justo ahora ya está definido para nosotros. – quux00

+0

Cuando porté este código a 1.4, declare que get-prng, mody y field-size son dinámicos. –

Cuestiones relacionadas