2009-08-08 7 views
6

J'ai un petit test unitaire macroAide à la conception d'une petite unité macro de test dans Clojure

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

Comment puis-je écrire correctement le message d'erreur? À l'heure actuelle, il donne

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 

Je veux évaluer l'expression et dire « oui si les résultats de valeur évalués devraient autre imprimer l'erreur avec la expression non évaluée au lieu de la valeur après « In ».

Répondre

11

Réponse originale

Je pense que c'est ce que vous cherchez:

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

ce que (quote ~expr) n'est apporter le s-expression représentée par expr dans votre « modèle », mais empêche d'être évalué, puis en appliquant str à l'expression s non évaluée, il en fait une chaîne de concaténation avec les autres chaînes du message d'erreur. Ainsi,:

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

produit le comportement souhaité.

Plutôt que d'utiliser 'yes signaler le succès, vous pouvez simplement utiliser true comme le rapport pour le succès de l'épreuve, ce qui donne:

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

et en évitant le problème de 'yes être retourné comme un symbole qualifié. Si vous avez besoin d'un symbole pour une raison quelconque, vous pourriez faire un mot-clé:

(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 



Réponse à la question posée dans les commentaires

Vous avez demandé dans les commentaires:

Je suis désolé d'avoir été plus clair dans ma question. Quelle serait la différence entre un symbole et un mot-clé dans ce cas?

Tenez compte de votre définition originale (avec la correction à faire l'erreur retour la façon dont vous voulez):

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

Je suppose que vous voulez que la pensée 'yes que vous pouvez utiliser pour tester contre 'yes dans d'autres contextes (on voit souvent ces types de tests dans des textes de lisp d'introduction). Mais 'yes est utilisé dans la définition macro, elle retourne un symbole qualifié lorsque le test est passe:

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

Maintenant, ce n'est pas ce que vous voulez.Imaginez que vous avez dit ceci:

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

Pour obtenir une réponse true, vous auriez à dire (en utilisant une citation de syntaxe):

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

Si vous définissez votre macro pour revenir :yes, vous obtenir le retour checkable sans avoir à la syntaxe citation l'objet que vous utilisez pour faire la vérification:

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

Mais tout cela est superflu parce que vous êtes vraiment i INTERESSEES en si (+ 2 2) retours 4, à savoir si votre affirmation est true ou false plutôt que si 'yes égale `` oui or « oui ; you can just have it return true` et éviter cette étape de contrôle (dans le monde réel).

Dans tous les cas, pour comprendre ce que sont les symboles qualifiés, vous devez lire les docs on the clojure reader et this SO answer explaining the ins and outs of symbols in clojure.

+0

Merci. Mais pourquoi en avez-vous fait un mot-clé? Quelle serait la différence? – unj2

+1

Le problème avec le symbole cité est qu'il apparaît comme un symbole qualifié, comme vous l'avez noté. J'ai suggéré d'utiliser 'true' comme le meilleur remplacement, mais j'ai rejeté l'option d'utiliser un mot-clé si, pour une raison quelconque, vous aviez besoin de quelque chose de 'symbolique' pour faire comme le reste du programme. Je pense, cependant, que «vrai» est la voie à suivre dans l'abstrait. – Pinochle

+0

Je suis désolé d'avoir été plus clair dans ma question. Quelle serait la différence entre un symbole et un mot-clé dans ce cas? – unj2

0

Vous avez une préoccupation transversale lorsque vous avez la macro d'impression 'Is'. La macro 'Is' renvoie-t-elle une liste qui contient quelque chose comme ceci (: passez la réponse réelle-réponse-attendue) ou (: forme-échec-réponse-attendue-réponse). Vous avez probablement une macro DefTest pour agréger vos affirmations. C'est là que vous devriez pp votre réponse.

Questions connexes