In an attempt to learn more about Clojure's parallel computation functions, I devised the following task: calculate a factorial in parallel using pmap
, pcalls
and pvalues
.
The idea is to split the factorial sequence into sub-computations, reducing the final output of each.
Here is the obvious non-parallel function:
(defn factorial [n] (reduce * (range 1 (inc n))
pmap is fairly straight-forward:
(defn pmap-factorial [n psz]
(let [parts (partition-all psz (range 1 (inc n)))]
(reduce * (pmap #(apply * %) parts))))
However, with pvalues I had to resort to macros that return a computation function.
(defmacro pvalues-factorial [n psz]
(let [exprs (for [p (partition-all psz (range 1 (inc n)))]
(cons '* p))]
`(fn [] (reduce * (pvalues ~@exprs)))))
Similar approach with pcalls:
(defmacro pcalls-factorial [n psz]
(let [exprs (for [p (partition-all psz (range 1 (inc n)))]
`(fn [] (* ~@p)))]
`(fn [] (reduce * (pcalls ~@exprs)))))
So, I had to use macros for pcalls
and pvalues
. Does not seem ideal, but it was the only way I could accomplish the above (and perhaps indicates that pmaps
is the best practice for this use case).
Questions:
1) How could the code be made more correct / idiomatic?
2) Did I have to resort to macros for pvalues and pcalls, or have I overlooked another way of accomplishing my goal with these functions?