0
votes

My question ist about Clojures deftest macro or more generally about how to compare lists created by functions. But i´m new to Clojure and can´t recognize the specific cause. Maybe anyone else have an idea?

First the reported message:

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)))

But it is obviously that (= (a (not b) c) (a (not b) c)) quoted should be true instead.

Second the specific test code:

(deftest to-symbol-list-test 
(is (= '(a (not b) c) (to-symbol-list ["a" "(not b)" "c"]))))

Third the definition of 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))

The function even should convert nested vectors. It´s an example, other functions behave in the same manner. I guessed it could cause by different types. For example list vs lazy-seq and i compare the lazy function instead of the data, but the types seems to be correct. In REPL i get:

(type (to-symbol-list ["a" "(not b)" "c"]))
=> clojure.lang.PersistentList
2
I think you are falling trap to (symbol "(not b)")cfrick
You are right thats the problem, thanks :)Daniel

2 Answers

1
votes

to-symbol-list returns a list of 3 symbols, and doesn't recursively deal with the nested data structure. Unfortunately the second symbol prints the same as the correctly parsed data structure you're expecting. I think in this case you'd be better off using clojure.edn/read-string (docs here) which will parse your data structure as I think you're expecting.

(defn to-symbol-list [list-of-strings]
  (map edn/read-string list-of-strings))

(to-symbol-list ["a" "(not b)" "c"])

Also, as a hint to help diagnose this sort of thing in the future, you can pass an extra argument to clojure.test/is which will print out in the event of a failure. This can be the result of a function call, like:

(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))))))
0
votes

It seems that to-symbol-list turns "(not b)" string a symbol, but not a nested list. To fix that, you'll need to refactor that function to take parens into account. Say, if it sees ( as the first symbol of a string, it calls itself recursively appending the result into some kind of accumulator (SICP is full of such exercises by the way).