Functional programming 帮助在Clojure中设计小型单元测试宏

Functional programming 帮助在Clojure中设计小型单元测试宏,functional-programming,lisp,clojure,Functional Programming,Lisp,Clojure,我有一个小的单元测试宏 (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=&g

我有一个小的单元测试宏

  (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)
所做的是将
expr
表示的s表达式引入“模板”,但阻止对其求值,然后将
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


对评论中提出的问题的回答

你在评论中问道:


很抱歉,我的问题应该说得更清楚些。在这种情况下,符号和关键字之间有什么区别

考虑您的原始定义(通过更正使错误返回您想要的方式):

我想象你想要
'yes
思维,你可以用它来测试其他上下文中的
'yes
(人们经常在介绍性的lisp文本中看到这些类型的测试)。但是在宏定义中使用了
'yes
,当测试通过时,它返回一个限定符号:

user=> (is (+ 2 2) 4)
user/yes
现在,这不是你想要的。想象一下你这样说:

user=> (= 'yes (is (+ 2 2) 4))
false
要获得
true
答案,您必须这样说(使用语法引号):

如果将宏定义为返回
:yes
,则可以获得可检查的返回,而无需对用于执行检查的对象进行语法引用:

user=> (= :yes (is (+ 2 2) 4))
true
但这一切都是多余的,因为您真正感兴趣的是
(+2)
是否返回
4
,即您的断言是
真是
还是
,而不是
'yes
是否等于``yes
'yes
;您可以让它返回
true`并避免此检查步骤(在现实世界中)


在任何情况下,要了解合格符号是什么,您需要阅读和。

当您使用“Is”宏打印时,您会遇到横切问题。让“Is”宏返回一个包含以下内容的列表(:pass form实际答案预期答案)或(:fail form实际答案预期答案)。您可能有一个DefTest宏用于聚合断言。这就是你应该给出答案的地方。

谢谢。但你为什么要把它作为关键词呢?有什么区别吗?引用的符号的问题是,正如您所指出的,它是一个限定符号。我建议使用“true”作为最佳替代,但如果出于某种原因,您需要一些“symbolike”,而不得不以编写程序其余部分的方式,那么就放弃了使用关键字的选项。不过,我认为,抽象地说,这是正确的。很抱歉,我应该在我的问题上说得更清楚一些。在这种情况下,符号和关键字之间有什么区别?太棒了!谢谢。我希望我能对答案投更多的赞成票。请注意,“值”是经过两次评估的。最好用简体字把它包起来。
user=> (= `yes (is (+ 2 2) 4))
true
user=> (= :yes (is (+ 2 2) 4))
true