qzcx
qzcx

Reputation: 371

Collection of lines from a file

This should be an easy question, but I've spent several hours and I still don't understand how to properly use sets in Clojure. I'm attempting to read a file and store each line in a set. This is my code so far.

(def dictionary #{})
  ;(conj dictionary "hi")
  (defn readDictionary []
    (doseq [line (clojure.string/split-lines 
       (slurp "C:\\Working\\Other\\dictionary.txt"))]
      (println line)
      (conj dictionary line)))
  (readDictionary)

  (println dictionary)

I can append the "hi" string to the set and each line gets printed out within the doseq, but the set ends up blank when I print it out.

I've very familiar with OO programming, but functional programming is something new for me.

Upvotes: 3

Views: 209

Answers (2)

KobbyPemson
KobbyPemson

Reputation: 2539

Read lines from file into set

(with-open [rdr (clojure.java.io/reader "C:\\Working\\Other\\dictionary.txt")]
   (set (line-seq rdr)))

Upvotes: 1

Thumbnail
Thumbnail

Reputation: 13483

The problem is not with sets as such. The problem is that conj, like most of the core library, does not have side effects. So the expression:

(conj dictionary line)

... evaluates to dictionary with line added to it, leaving dictionary (and line) quite unchanged. So the doseq produces a sequence of sets, each containing one line.

The call

(readDictionary)

... evaluates this sequence of single-member sets, then discards it, since it is not bound to anything. Hence the call has no net effect.

I think you want something like this (untested):

(defn readDictionary [file-name]
  (into #{} (clojure.string/split-lines (slurp file-name))))

(def dictionary (readDictionary "C:\\Working\\Other\\dictionary.txt"))

(doseq [line dictionary] (println line))

In Clojure, you have to get used to working with pure (side-effect free) functions operating upon immutable/persistent data structures.

Upvotes: 6

Related Questions