2013-07-08 67 views
3

我想使用SQLKorma執行一些SQL語句。起初,我寫了下面的代碼:「For」失敗,但「循環」工作

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

但原因不明,這是行不通的。 for循環完全跳過。然而這工作:

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

爲什麼會發生這種情況?爲什麼for循環失敗?

+1

在Clojure'for'不是一個循環,它是列表理解。不要讓這個名字欺騙你。 – ivant

回答

4

for創建一個惰性序列。只有當你實際使用它時,Clojure纔會執行懶惰序列的每個元素。如果您只需要副作用,您應該強制執行延遲序列dorun

在你的情況我建議你使用map

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

doseqsee mtyaka's answer),而不是for

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

我喜歡map版本的更多,但是doseq工作的點點更快。

+1

地圖很懶就像是; mapv不是懶惰 – noisesmith

+0

是的,這就是爲什麼在我的例子中有一個'dorun'。 –

+0

我根據mtyaka的回答添加了'doseq'示例。 –

8

for是懶惰的。改爲使用doseq

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