我有一个小单元测试宏
(defmacro is [expr value] `(if (= ~expr ~value) 'yes (println "Expected " ~value "In" ~expr "But Evaluated to" ~expr)))
如何正确编写错误消息?现在它给出了
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
我想评估表达式并说'是,如果评估的值匹配预期,否则使用未评估的表达式而不是"In"之后的值打印错误.
原始答案
我认为这就是你要找的东西:
(defmacro is [expr value] `(if (= ~expr ~value) true (println "Expected " ~value "In" (str (quote ~expr)) "But Evaluated to" ~expr)))
什么(quote ~expr)
是将表示的s表达式expr
带入您的"模板",但阻止它被评估,然后应用于未评估str
的s表达式使其成为一个字符串,用于与错误消息的其他字符串连接.所以,:
user=> (is (+ 2 2) 5) Expected 5 In (+ 2 2) But Evaluated to 4
产生所需的行为.
'yes
您可以简单地true
将报告用作测试成功的报告,而不是用于报告成功,给出:
user=> (is (+ 2 2) 4) true
并避免'yes
作为合格符号返回的问题.如果由于某种原因需要符号,那么您可以创建一个关键字:
(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
答案问题在评论中提问
你在评论中问道:
对不起,我的问题本来应该更清楚.在这种情况下,符号和关键字之间有什么区别?
考虑您的原始定义(通过更正使错误以您想要的方式返回):
(defmacro is [expr value] `(if (= ~expr ~value) 'yes (println "Expected " ~value "In" (str (quote ~expr)) "But Evaluated to" ~expr)))
我想你想要在其他环境中'yes
用来测试的思想'yes
(人们经常在介绍性的lisp文本中看到这些类型的测试).但是'yes
在宏定义中使用它,它会在测试通过时返回一个限定符号:
user=> (is (+ 2 2) 4) user/yes
现在,这不是你想要的.想象一下,你这样说:
user=> (= 'yes (is (+ 2 2) 4)) false
要得到true
答案,你必须这样说(使用语法引用):
user=> (= `yes (is (+ 2 2) 4)) true
如果您定义了要返回的宏:yes
,那么您将获得可检查的返回,而无需语法引用您用于执行检查的对象:
user=> (= :yes (is (+ 2 2) 4)) true
但是,这一切都是多余的,因为你是在是否真正有兴趣(+ 2 2)
的回报4
,即你的断言是否true
还是false
而非是否'yes
平等``是or
"是; you can just have it return
TRUE`和避免这个检查步骤(在现实世界中).
在任何情况下,要了解什么是合格的符号,你需要阅读clojure阅读器上的文档和这个SO答案,解释clojure中符号的来龙去脉.