理解期货与懒惰之间的相互作用

时间:2014-09-24 23:38:32

标签: clojure lazy-evaluation future

一周前,我问了一个类似的问题(Link),在那里我了解到地图的懒惰特性使得以下代码顺序运行。

(defn future-range
  [coll-size num-futures f]
  (let [step (/ coll-size num-futures)
        parts (partition step (range coll-size))
        futures (map #(future (f %)) parts)]      ;Yeah I tried doall around here...
    (mapcat deref futures)))

这是有道理的。但是我该如何解决呢?我几乎尝试了所有的东西(:D),一种与承诺和许多其他事物不同的方法。它只是不想工作。为什么?在我看来,在mapcat derefs之前,期货才会开始(我用Thread / sleep进行了一些测试)。但是当我完全意识到doall的序列不应该在另一个线程中立即开始期货?

1 个答案:

答案 0 :(得分:2)

看来你已经在那里了。如果你将(map #(future (f %)) parts)包裹在(doall ...)中,它就可以了。只需重新启动您的repl并从干净的平板开始,以确保您正在调用正确的函数版本。

(defn future-range
  [coll-size num-futures f]
  (let [step (/ coll-size num-futures)
        parts (partition step (range coll-size))
        futures (doall (map #(future (f %)) parts))]
    (mapcat deref futures)))

您可以使用以下方法对其进行测试。

(defn test-fn [x]
  (let [start-time (System/currentTimeMillis)]
    (Thread/sleep 300)
    [{:result x
      :start start-time
      :end-time (System/currentTimeMillis)}]))

(future-range 10 5 test-fn)

您也可以使用time来衡量5次(Thread/sleep 300)只需要300毫秒的时间:

(time (future-range 10 5 (fn [_] (Thread/sleep 300))))