如果比较列表,Clojure 的 deftest 宏中的断言错误
Assertion error in Clojure's deftest macro if comparing lists
我的问题是关于 Clojures deftest 宏,或者更笼统地说是关于如何比较由函数创建的列表。但我是 Clojure 的新手,无法识别具体原因。也许其他人有想法?
首先报告的消息:
FAIL in (to-symbol-list-test) (util_test.clj:105)
expected: (= (quote (a (not b) c)) (to-symbol-list ["a" "(not b)" "c"]))
actual: (not (= (a (not b) c) (a (not b) c)))
但显然 (= (a (not b) c) (a (not b) c)) quoted 应该是正确的。
第二个具体测试代码:
(deftest to-symbol-list-test
(is (= '(a (not b) c) (to-symbol-list ["a" "(not b)" "c"]))))
第三个to-symbol-list的定义:
(defn to-symbol-list [term]
"Converts a vector based term into a list based term
by converting its elements into symbols recursivly"
(postwalk
#(if (string? %)
(symbol %)
(reverse (into '() %)))
term))
该函数甚至应该转换嵌套向量。这是一个例子,其他功能的行为方式相同。我猜这可能是由不同类型引起的。例如 list vs lazy-seq,我比较的是惰性函数而不是数据,但类型似乎是正确的。在 REPL 中我得到:
(type (to-symbol-list ["a" "(not b)" "c"]))
=> clojure.lang.PersistentList
似乎 to-symbol-list
将 "(not b)"
字符串变成一个符号,而不是一个嵌套列表。要解决此问题,您需要重构该函数以将括号考虑在内。比如说,如果它看到 (
作为字符串的第一个符号,它会调用自己递归地将结果附加到某种累加器中(顺便说一下,SICP 充满了这样的练习)。
to-symbol-list
returns 3个符号的列表,不递归处理嵌套数据结构。不幸的是,第二个符号打印出与您期望的正确解析的数据结构相同的结果。我认为在这种情况下,您最好使用 clojure.edn/read-string
(docs here),它将按照您的预期解析您的数据结构。
(defn to-symbol-list [list-of-strings]
(map edn/read-string list-of-strings))
(to-symbol-list ["a" "(not b)" "c"])
此外,作为将来帮助诊断此类问题的提示,您可以向 clojure.test/is
传递一个额外的参数,该参数将在出现故障时打印出来。这可能是函数调用的结果,例如:
(ns to-symbols-test
(:require [clojure.edn :as edn]
[clojure.test :refer [deftest is are testing] :as t]
[clojure.data :as data]
[clojure.pprint :as pp]))
(defn to-symbol-list [l]
(map edn/read-string l))
(defn diff [a b]
(with-out-str (pp/pprint (take 2 (data/diff a b)))))
(deftest test-to-symbol-list
(testing "to-symbol-list should convert recursively"
(let [expected '(a (not b) c)
result (to-symbol-list ["a" "(not b)" "c"])]
(is (= expected result (diff expected result))))))
我的问题是关于 Clojures deftest 宏,或者更笼统地说是关于如何比较由函数创建的列表。但我是 Clojure 的新手,无法识别具体原因。也许其他人有想法?
首先报告的消息:
FAIL in (to-symbol-list-test) (util_test.clj:105)
expected: (= (quote (a (not b) c)) (to-symbol-list ["a" "(not b)" "c"]))
actual: (not (= (a (not b) c) (a (not b) c)))
但显然 (= (a (not b) c) (a (not b) c)) quoted 应该是正确的。
第二个具体测试代码:
(deftest to-symbol-list-test
(is (= '(a (not b) c) (to-symbol-list ["a" "(not b)" "c"]))))
第三个to-symbol-list的定义:
(defn to-symbol-list [term]
"Converts a vector based term into a list based term
by converting its elements into symbols recursivly"
(postwalk
#(if (string? %)
(symbol %)
(reverse (into '() %)))
term))
该函数甚至应该转换嵌套向量。这是一个例子,其他功能的行为方式相同。我猜这可能是由不同类型引起的。例如 list vs lazy-seq,我比较的是惰性函数而不是数据,但类型似乎是正确的。在 REPL 中我得到:
(type (to-symbol-list ["a" "(not b)" "c"]))
=> clojure.lang.PersistentList
似乎 to-symbol-list
将 "(not b)"
字符串变成一个符号,而不是一个嵌套列表。要解决此问题,您需要重构该函数以将括号考虑在内。比如说,如果它看到 (
作为字符串的第一个符号,它会调用自己递归地将结果附加到某种累加器中(顺便说一下,SICP 充满了这样的练习)。
to-symbol-list
returns 3个符号的列表,不递归处理嵌套数据结构。不幸的是,第二个符号打印出与您期望的正确解析的数据结构相同的结果。我认为在这种情况下,您最好使用 clojure.edn/read-string
(docs here),它将按照您的预期解析您的数据结构。
(defn to-symbol-list [list-of-strings]
(map edn/read-string list-of-strings))
(to-symbol-list ["a" "(not b)" "c"])
此外,作为将来帮助诊断此类问题的提示,您可以向 clojure.test/is
传递一个额外的参数,该参数将在出现故障时打印出来。这可能是函数调用的结果,例如:
(ns to-symbols-test
(:require [clojure.edn :as edn]
[clojure.test :refer [deftest is are testing] :as t]
[clojure.data :as data]
[clojure.pprint :as pp]))
(defn to-symbol-list [l]
(map edn/read-string l))
(defn diff [a b]
(with-out-str (pp/pprint (take 2 (data/diff a b)))))
(deftest test-to-symbol-list
(testing "to-symbol-list should convert recursively"
(let [expected '(a (not b) c)
result (to-symbol-list ["a" "(not b)" "c"])]
(is (= expected result (diff expected result))))))