Daniel Ziltener
Daniel Ziltener

Reputation: 657

"For" fails but "loop" works

I want to execute some SQL statements using SQLKorma. At first I wrote the following code:

(let [sqls (-> (slurp "resources/database.sql")
              (str/split #";")
              butlast)]
  (for [sql sqls]
      (k/exec-raw sql)))

But for reasons unknown, this does not work. The for loop gets skipped completely. This however works:

(let [sqls (-> (slurp "resources/database.sql")
              (str/split #";")
              butlast)]
  (loop [sqls sqls]
    (if (not (empty? sqls))
      (do
        (k/exec-raw (first sqls))
        (recur (rest sqls))))))

Why does this happen? Why does the for loop fail?

Upvotes: 3

Views: 105

Answers (2)

Leonid Beschastny
Leonid Beschastny

Reputation: 51500

for creates a lazy sequence. Clojure executes each element of the lazy sequence only when you actually use it somehow. If you need only side effects you should force the execution of the lazy sequence with dorun.

In your case I'd recommend you to use map

(->> (str/split (slurp "resources/database.sql")
                #";")
     butlast
     (map k/exec-raw)
     dorun)

or doseq (see mtyaka's answer) instead of for loop

(doseq [sql (-> (slurp "resources/database.sql")
                (str/split #";")
                butlast)]
  (k/exec-raw sql))

I like map version more, howeverdoseq works a little bit faster.

Upvotes: 4

mtyaka
mtyaka

Reputation: 8848

for is lazy. Use doseq instead:

(doseq [sql sqls]
  (k/exec-raw sql))

Upvotes: 8

Related Questions