Допустим, я определяю последовательность всех натуральных чисел следующим образом:
(def naturals (iterate inc 0))
Я также определяю функцию, отображающую натуральные числа в ноль, для вычисления которой требуется некоторое время, вот так:
(defn hard-comp [_] (Thread/sleep 500))
Обратите внимание на время вычисления для вычисления следующих s-выражений, измеренное как clojure.core/time
.
(dorun (map hard-comp (range 30))) ;
15010,367496 мсек
(dorun (pmap hard-comp (range 30))) ;
537.044554 мсек
(dorun (map hard-comp (doall (take 30 naturals))))) ;
15009,488499 мсек
(dorun (pmap hard-comp (doall (take 30 naturals)))) ;
3004,499013 мсек
(doall (take 30 naturals)) ;
0,385724 мсек
(range 30)
; 0,159374 мсек
pmap
в ~ 6 раз быстрее при вызове с явным диапазоном, чем с частью натуральных чисел.
Так как (= (range 30) (take 30 naturals))
возвращает true и оба объекта имеют тип clojure.lang.LazySeq
, и clojure вычисляет все аргументы функции перед вызовом функции, как объяснить вышеупомянутые детали синхронизации?