0
\$\begingroup\$

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?

asked Aug 28, 2012 at 21:24
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

1) that is quite idomatic Clojure from what I have seen.

2) macros are "contagious" if the thing you are trying to call is a macro and you want to do anything requiring first-class-functions (map apply reduce etc...) then the thing doing the applying must it's self be a macro.

This is why the coding standards for clojure.contrib stable releases require that your library provide a non-macro way to access it's services in addition to the macro one. as your problem nicely demonstrates. macros are incredibly useful, and they are not first class

answered Aug 28, 2012 at 22:06
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.