2009-08-08 9 views
6

tengo una pequeña prueba de unidad macroAyuda en el diseño de una pequeña macro de prueba unitaria en Clojure

(defmacro is [expr value] 
     `(if (= ~expr ~value) 
      'yes 
      (println "Expected " ~value "In" ~expr "But Evaluated to" ~expr))) 

¿Cómo escribir correctamente el mensaje de error? En este momento se da

Clojure 1.0.0- 
1:1 user=> (is (+ 2 2) 4) 
user/yes 
1:2 user=> (is (+ 2 2) 5) 
Expected 5 In 4 But Evaluated to 4 

Deseo evaluar la expresión y decir 'sí, si los partidos valor evaluado espera que los demás impresión del error con la expresión sin evaluar en lugar del valor después de 'En'.

Respuesta

11

respuesta original

Creo que esto es lo que busca:

(defmacro is [expr value] 
    `(if (= ~expr ~value) 
     true 
     (println "Expected " ~value "In" (str (quote ~expr)) 
        "But Evaluated to" ~expr))) 

lo (quote ~expr) no es llevar el s-expresión que constituyen expr en su "plantilla", pero lo impide de ser evaluado, luego aplicar str a la expresión-s no evaluada lo convierte en una cadena para la concatenación con las otras cadenas del mensaje de error. Por lo tanto,:

user=> (is (+ 2 2) 5) 
Expected 5 In (+ 2 2) But Evaluated to 4 

produce el comportamiento deseado.

En lugar de utilizar 'yes reportar el éxito, puede simplemente usar true como el informe para el éxito de la prueba, dando:

user=> (is (+ 2 2) 4) 
true 

y evitar el problema de 'yes que se devuelven como un símbolo cualificado. Si necesita un símbolo, por alguna razón, entonces se podría hacer una palabra clave:

(defmacro is [expr value] 
    `(if (= ~expr ~value) 
     :yes 
     (println "Expected " ~value "In" (str (quote ~expr)) 
        "But Evaluated to" ~expr))) 


user=> (is (+ 2 2) 4) 
:yes 



respuesta a pregunta planteada en Comentarios

Pediste en los comentarios:

Lamento haber sido más claro en mi pregunta. ¿Cuál sería la diferencia entre un símbolo y una palabra clave en este caso?

Tenga en cuenta su definición original (con la corrección a que el error devuelve la forma en que quería):

(defmacro is [expr value] 
`(if (= ~expr ~value) 
    'yes 
    (println "Expected " ~value "In" (str (quote ~expr)) 
       "But Evaluated to" ~expr))) 

Imagino que desea que el pensamiento 'yes que se puede utilizar para probar contra 'yes en otra contextos (a menudo se ve este tipo de pruebas en textos introductorios de ceceo). Pero 'yes se utiliza en su macro definición, se vuelve un símbolo cualificado cuando la prueba es pases:

user=> (is (+ 2 2) 4) 
user/yes 

Ahora, esto no es lo que cabe esperar.Imagínese que usted ha dicho esto:

user=> (= 'yes (is (+ 2 2) 4)) 
false 

para obtener una respuesta true, que tendría que decir esto (utilizando el precio de sintaxis):

user=> (= `yes (is (+ 2 2) 4)) 
true 

Si ha definido su macro para volver :yes, entonces obtener la devolución comprobable sin necesidad de sintaxis cita el objeto que está utilizando para hacer la revisión:

user=> (= :yes (is (+ 2 2) 4)) 
true 

Pero todo esto es innecesario ya que realmente son i INTERESADAS en (+ 2 2) si vuelve 4, es decir, si su afirmación es true o false en lugar de si 'yes es igual a `` sí or 'sí ; you can just have it return true` y evita este paso de comprobación (en el mundo real).

En cualquier caso, para comprender qué son los símbolos calificados, debe leer docs on the clojure reader y this SO answer explaining the ins and outs of symbols in clojure.

+0

Gracias. Pero, ¿por qué lo convirtió en una palabra clave? ¿Cuál sería la diferencia? – unj2

+1

El problema con el símbolo citado es que aparece como un símbolo calificado, como ha señalado. Sugerí usar 'verdadero' como el mejor reemplazo, pero descarté la opción de usar una palabra clave si, por alguna razón, necesitabas algo 'parecido a un símbolo' por razones que tenían que ver con la forma en que escribiste el resto del programa. Creo, sin embargo, que "verdadero" es el camino a seguir en abstracto. – Pinochle

+0

Lo siento, debería haber sido más claro en mi pregunta. ¿Cuál sería la diferencia entre un símbolo y una palabra clave en este caso? – unj2

0

Tiene una intersección cuando tiene la macro 'Es'. Haga que la macro 'Es' devuelva una lista que contenga algo como esto (: pase la respuesta-espera-respuesta real) o (: responda-espere la respuesta-esperada). Probablemente tenga una macro DefTest para agregar sus afirmaciones. Ahí es donde debes pp tu respuesta.