The Haskell code below uses par
and pseq
to do some multicore number-crunching as a toy to show several cores being used. What would be the easiest and most idiomatic way to express this in Scala? Futures and Promises seem promising (ahem) and I have been looking at scalaz.concurrent
, e.g. this example, but I can't find docs to explain it all.
import Control.Parallel
main = a `par` b `par` c `pseq` print (a + b + c)
where
a = ack 3 10
b = fac 42
c = fib 35
fac 0 = 1
fac n = n * fac (n-1)
ack 0 n = n+1
ack m 0 = ack (m-1) 1
ack m n = ack (m-1) (ack m (n-1))
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
You can translate your example in Scala like so:
import concurrent.{Await, Future, future}
import concurrent.ExecutionContext.Implicits.global
import concurrent.duration.Duration
object Main extends App {
val fac: Int => Int = {
case 0 => 1
case n => n * fac(n-1)
}
val ack: (Int, Int) => Int = {
case (0, n) => n + 1
case (m, 0) => ack (m-1, 1)
case (m, n) => ack (m-1, ack(m, n-1))
}
val fib: Int => Int = {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
val fa = future { ack(3, 10) }
val fb = future { fac(42) }
val fc = future { fib(35) }
val x = for (((a, b), c) <- fa zip fb zip fc) yield (a + b + c)
val result = Await.result(x, Duration.Inf) //awaiting synchronously after the result
println(s"Value is: $result")
}
The future { fib(3, 10) }
bit will create an asynchronous computation which will run on a different execution thread and will return a Future
object. You can then compose all your futures into one big future which will provide the list of all the results, using Future.sequence
.
We can map the result of this latter future into the sum of the results, thus obtaining the final value.
With this final future we can do several things. We can compose it further or we can attach callbacks on it or we can wait synchronously for a specified duration of time. In my example I am waiting in a synchronous fashion after the result for an infinite period of time.