2014-09-24 2 views
0

Неделю назад я задал аналогичный вопрос (Link), где я узнал, что ленивый характер карты делает следующий код последовательным.Понимание взаимодействия между фьючерсами и lazy-seq

(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 не сделает их (я сделал несколько тестов с Thread/sleep). Но когда я полностью понимаю последовательность с doall, не следует ли фьючерсы начинать сразу в другом потоке?

ответ

2

Кажется, вы уже находитесь. Он работает, если вы оберните (map #(future (f %)) parts) в (doall ...). Просто перезапустите свой реплика и начните с чистого листа, чтобы убедиться, что вы вызываете правильную версию своей функции.

(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)))) 
Смежные вопросы