5

我需要根据 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) 的实现运行速度明显更快。但是,当我转到文件夹并观看文件时,它会在给定 Elapsed time 后继续写入,并且 (nil ...) 输出会等到它完成写入以显示。这使我相信他们实际上都在花费相同的时间。

那么,在这种情况下使用doseq 和map 有什么区别呢?哪种方式总体上会更好?谢谢

4

1 回答 1

3

doseq 是急切的(不是懒惰的),当你调用它时会做所有的工作。 map 是惰性的,并立即返回一个惰性序列,表示读取结果时将发生的工作。

因此,当 repl 打印地图的结果(所有 nil)而不是您正在计时的部分时,地图正在工作。要解决此问题,请拨打电话doalldorun围绕电话map

(time (doall (out2 nums)))

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

于 2013-07-22T21:12:38.600 回答