Я реализовал Решето Эратосфена, используя стандартную библиотеку Clojure.
(defn primes [below]
(remove (set (mapcat #(range (* % %) below %)
(range 3 (Math/sqrt below) 2)))
(cons 2 (range 3 below 2))))
Я думаю, что это должно быть поддается параллелизму, так как здесь нет рекурсии, и можно добавить редукторные версии remove и mapcat. Вот что я придумал:
(defn pprimes [below]
(r/foldcat
(r/remove
(into #{} (r/mapcat #(range (* % %) below %)
(into [] (range 3 (Math/sqrt below) 2))))
(into [] (cons 2 (range 3 below 2))))))
Я разлил исходный набор и сгенерированные множители в векторы, так как понимаю, что LazySeq не складывается. Кроме того, для окончательной реализации коллекции используется r / foldcat.
Моя проблема в том, что это немного медленнее, чем первая версия.
(time (first (primes 1000000))) ;=> approx 26000 seconds
(time (first (pprimes 1000000))) ;=> approx 28500 seconds
Слишком много накладных расходов от координирующих процессов или я неправильно использую редукторы?