As you've noticed, reduceLeft
is not parallelizable, as it explicitly assumes a form that is not associative: (B,A) => B
.
As long as you use an associative operator, reduce
is parallelizable.
There's also an analog of foldLeft
called aggregate
that takes two functions: one to map into a combinable form, and two an associative one to merge the elements: (B,A)=>B, (B,B) => B
.
This one, as long as the two functions will agree on the output, and you have a zero to mix in wherever you want, is parallelizable.
So if you want to be able to be parallel,
reduceLeft/Right -> reduce
foldLeft/Right -> aggregate
There may be some cases where reduce
is more restrictive than reduceLeft
but aggregate
will do the trick.
That said, this only makes the statement able to be parallel. For it to actually be parallel you need to use a collection that inherits from ParIterable
, and these all have Par
in their names: ParVector
, etc.. The easiest way to get a parallel collection is to call .par
on a regular one (.seq
goes the other way, from parallel to non-parallel). It's done this way because in general there's no reason to be parallel except for speed, but parallelism adds overhead. So you should only operate in parallel if there's enough work to do, and while you may know that, the compiler probably doesn't. Thus, you are to explicitly select which kind of collection you want. (Parallel collections return parallel, and sequential return sequential.)