2
votes

Hi I need to return string from stringify function, but currently I'm getting lazy seq. Can't wrap my head how to evaluate lazy seq.

So what I need is to have chain call like this: (println "Formated: " (fmt (stringify m)))

(defn stringify [m]
    "Construct string expression"
    (let [res (reduce-kv (fn [acc k v]
                    (let [s (str/join "" [v (name k)])]
                      (if (pos? v)
                        (if (empty? acc)
                          (concat acc ["+" s])
                          (concat acc s))
                        (concat acc s))
                      ))

          "" m)]
      res))

(defn fmt [s]
    "Apply formating rules"
    (-> s
        (.replaceAll "([+-])" " $1 ")
        (println)))
2
I would consider using clojure.string/replace instead of Java interop and .replaceAll.Toni Vanhala

2 Answers

3
votes

concat operates on seqs, not strings. It works on strings, but treats them as sequences of characters. It returns a lazy seq, which you can realize into a string with clojure.string/join.

Replacing the last statement res in your stringify function with (clojure.string/join "" res) should do the trick. However, you could build a string with reduce-kv from the get-go, using join instead of concat. You can reduce into anything, not just collections/seqs.

2
votes

When dealing with strings, just use str for concatenation:

(concat acc s))         => (str acc s)
(concat acc ["+" s])    => (apply str [acc "+" s])  ; note moved `[`

examples:

=> (str "abc" "def")
"abcdef"

=> (apply str ["abc"  "de" "fgh"] )
"abcdefgh"

=> (clojure.string/join ["abc"  "de" "fgh"] )  ; like `(apply str...)`