Ошибка утверждения в макросе deftest Clojure при сравнении списков
Мой вопрос о макросе defj Clojures или в целом о том, как сравнивать списки, созданные функциями. Но я новичок в Clojure и не могу распознать конкретную причину. Может быть, у кого-нибудь еще есть идея?
Сначала сообщаемое сообщение:
FAIL in (to-symbol-list-test) (util_test.clj: 105)
ожидается: (= (цитата (a (не b) c)) (список символов ["a" "(не b)" "c"]))
фактический: (не (= (a (не b) c) (a (не b) c)))
Но очевидно, что вместо (= (a (не b) c) (a (не b) c)) следует указывать значение true.
Второй конкретный код теста:
(deftest to-symbol-list-test
(is (= '(a (not b) c) (to-symbol-list ["a" "(not b)" "c"]))))
Третье определение списка символов:
(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
2 ответа
to-symbol-list
возвращает список из 3 символов и не рекурсивно обрабатывает вложенную структуру данных. К сожалению, второй символ печатает так же, как и правильно проанализированная структура данных, которую вы ожидаете. Я думаю, что в этом случае вам лучше использовать clojure.edn/read-string
( документы здесь), которые проанализируют вашу структуру данных, как я думаю, вы ожидаете.
(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))))))
Кажется, что to-symbol-list
витки "(not b)"
строка символа, но не вложенный список. Чтобы это исправить, вам нужно будет реорганизовать эту функцию, чтобы учесть парены. Скажи если видит (
как первый символ строки, он вызывает себя рекурсивно, добавляя результат в какой-то аккумулятор (кстати, SICP полон таких упражнений).