Newbie: adding items to a global vector in doseq

478 views
Skip to first unread message

phi...@free.fr

unread,
Aug 14, 2014, 12:05:25 PM8/14/14
to clo...@googlegroups.com

Hello,

I am trying to add URLs contained in a text file (eg. apple.com, ibm.com...), to a global vector called url2, but to no avail, the vector remains empty.

Any suggestions would be greatly appreciated.

Many thanks.

Philippe


(def fich "data.txt")
 
(def urls2 (vec nil))
 
(defn readf [file]
    (let [x (vec nil)]
        (with-open [r (clojure.java.io/reader file)]
            (doseq [line (line-seq r)]
                (conj urls2 (re-find #"\w+\.\w+" line))))))


(defn -main []
    (do
    (readf fich)
    (println urls2)))

Mike Fikes

unread,
Aug 14, 2014, 12:49:20 PM8/14/14
to clo...@googlegroups.com
Read up on atoms. The results of your conj call are being discarded.

For example, check out the behavior of this:

(def urls2 (atom []))
(swap! urls2 conj "http://foo.bar")

phi...@free.fr

unread,
Aug 14, 2014, 2:28:57 PM8/14/14
to clo...@googlegroups.com
Hi Mike,

I have read up on atoms and used swap! to set the urls2 vector atom in my code. Thanks.

One problem remains though: I can't retrieve the atom vector's items

(nth urls 10)

throws the following exception

java.lang.UnsupportedOperationException: nth not supported on this type: Atom

and

(doseq [x urls]
            (println x))))


java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Atom

Philippe



Philippe

phi...@free.fr

unread,
Aug 14, 2014, 2:33:53 PM8/14/14
to clo...@googlegroups.com
Just solved the problem by prepending at at-sign, in both cases:

(nth @urls 10)

(doseq [x @urls]
   (println x))

Thomas Heller

unread,
Aug 14, 2014, 5:13:18 PM8/14/14
to clo...@googlegroups.com
Hey,

it's not how you'd usually do things in Clojure and I'd consider the use of an atom in this place as "wrong".

I was struggling with Clojure in the beginning too and my code looked pretty much like yours, but the faster you get into the Clojure mindset the easier it will be.

This might be hard to understand at first but if you wrap your head arround whats happening you are halfway there to understanding Clojure:

(defn readf [file]
  (with-open [r (clojure.java.io/reader file)]
    (->> (line-seq r)
         (map #(re-find #"\w+\.\w+" %))
         (into []))))

(defn -main []
  (let [urls (readf fich)]
    (println urls)))


Try to use atoms for what they are meant (multi-threaded, concurrent code), not to emulate mutable local state.

HTH,
/thomas

Mike Fikes

unread,
Aug 14, 2014, 6:01:34 PM8/14/14
to clo...@googlegroups.com
Thomas is absolutely right, Philippe.

Things also get easier if you avoid, or defer side effects, and first focus on pure functions.

So, for example at the REPL, you might first try processing a literal sequence of lines, repeatedly adjusting the processing code, tweaking the regex, until you get it right:

(mapv #(re-find #"\w+\.\w+" %) ["abc def.g" "apple.com ibm.com foo"])
;=> ["apple.com" "ibm.com"]

You could turn the above into a pure function that works on a sequence of lines:

(defn lines->urls [lines] (mapv #(re-find #"\w+\.\w+" %) lines))


You could then define your file reading code in terms of that pure function:


(defn readf [file]

   (with-open [r (clojure.java.io/reader file)]

      (lines->urls (line-seq r))))

Tassilo Horn

unread,
Aug 15, 2014, 2:41:10 AM8/15/14
to phi...@free.fr, clo...@googlegroups.com
phi...@free.fr writes:

> I have read up on atoms and used swap! to set the urls2 vector atom in
> my code. Thanks.
>
> One problem remains though: I can't retrieve the atom vector's items
>
> *(nth urls 10)*
>
> throws the following exception
>
> java.lang.UnsupportedOperationException: nth not supported on this
> type: Atom

To access the current value of an atom, you need to dereference it:

(nth @urls 10)

Bye,
Tassilo
Reply all
Reply to author
Forward
0 new messages