Clojure写入文件映射vs doseq

时间:2013-07-22 20:51:59

标签: time map clojure output

我需要根据Clojure集合的元素将一些东西写入文件中,我可以这样做 - 但是我遇到了让我感到困惑的事情。这可能是因为我不完全理解时间宏,但是当我执行以下操作时:

=> (def nums (take 100000 (repeatedly #(str (rand-int 1000) " "))))
   (defn out1 [nums] (doseq [n nums] (spit "blah1.txt" n :append true)))
   (defn out2 [nums] (map #(spit "blah2.txt" % :append true) nums))
#'test.core/nums
#'test.core/out1
#'test.core/out2
=> (time (out1 nums))
"Elapsed time: 19133.247 msecs"
nil
=> (time (out2 nums))
"Elapsed time: 0.209 msecs"
(nil nil nil nil ... )

使用map(out2)的实现运行速度明显加快。但是,当我进入文件夹并观察文件时,它会在给定经过时间后继续进行写入,并且(nil ...)输出等待,直到它完成写入显示。这让我相信他们实际上都在同一时间。

那么,在这种情况下使用doseq和map之间的区别是什么?哪种方式整体会更好?感谢

1 个答案:

答案 0 :(得分:3)

doseq非常渴望(不是懒惰),并在你调用它时完成所有工作。 map是lazy并立即返回一个惰性序列,表示读取结果时将发生的工作。

所以地图正在进行工作,当repl打印地图的结果(所有的nils)不在你正在计时的部分。要解决此问题,请拨打doalldorun来调用map

(time (doall (out2 nums)))

更重要的错误是您不打印结果(或以其他方式使用它),然后根本不会将内容写入文件。通常,对于纯粹的副作用操作doseq可能是更好的选择。