I'm trying to understand the idea and purpose behind scalaz concurrent package, primarily Future and Task classes, but when using them in some application, it's now far from simple sequential analog, whereas scala.concurrent.Future
, works more then better. Can any one share with his experience on writing concurrent/asynchronous application with scalaz, basically how to use it's async
method correctly? As i understand from the sources async
doesn't use a separate thread like the call to standard future
, or fork/apply
methods from scalaz works, so why it is called async
then? Does it mean that in order to get real concurrency with scalaz i always have to call fork(now(...))
or apply
?
I'm not a scalaz expert, but I'll try to help you a little bit. Let me try answer your questions one by one:
1) Can any one share with his experience on writing concurrent/asynchronous application with scalaz, basically how to use it's async method correctly?
Let's first take a look at async
signature:
def async[A](listen: (A => Unit) => Unit): Future[A]
This could be a bit cryptic at first, so as always it's good idea to look at tests to understands possible use cases. In https://github.com/scalaz/scalaz/blob/scalaz-seven/tests/src/test/scala/scalaz/concurrent/FutureTest.scala you can find the following code:
"when constructed from Future.async" ! prop{(n: Int) =>
def callback(call: Int => Unit): Unit = call(n)
Future.async(callback).run must_==
}
As we know from signature Future.async
just construct new Future using function of signature (A => Unit) => Unit
. What this really means is that Future.async takes as parameter function which for given callback makes all required computations and pass the result to that callback.
What is important to note it that Future.async
does not run any computations on itself, it only prepare structure to run them later.
2) As i understand from the sources async doesn't use a separate thread like the call to standard future, or fork/apply methods from scalaz works, so why it is called async then?
You are correct. Only fork
and apply
seems to be running anything using threads, which is easy to notice looking at the signatures which contains implicit pool: ExecutorService
. I cannot speak for the authors here, but I guess async is related to the callback. It means that rather than blocking on Future to get it result at the end you will use asynchronous callback.
3) Does it mean that in order to get real concurrency with scalaz i always have to call fork(now(...)) or apply?
From what I can say, yes. Just notice that when you are creating Future using syntax Future(x)
you are using apply
method here, so this is kind of default behavior (which is fine).
If you want to better understand design of Scalaz Futures I can recommend you reading "Functional Programming in Scala". I believe this book is written by main Scalaz contributors and chapter 7 discusses designing API for purely functional parallelism library. It's not exactly the same as Scalaz Future, but you can see many similarities.
You can also read wonderful Timothy Perrett blog post about Scalaz Task and Future which covers many not so obvious details.
async
is used to adapt an async, callback-based API as a Future
. It's called async
because it's expected that it will be used with something that runs asynchronously, perhaps calling the callback from another thread somewhere further down the line. This is "real" concurrency, provided the API you're calling really uses it asynchronously (e.g. I use Future.async
with the async parts of the AWS SDK like AmazonSimpleDBAsyncClient
).
If you want "real" concurrency from the scalaz Task
API directly you need to use things like fork
or gatherUnordered
, as many of the APIs default towards being safe/deterministic and restartable, with concurrency only when explicitly requested.
When composing Tasks with map and flatMap you can get a performance win by not using fork, see:
http://blog.higher-order.com/blog/2015/06/18/easy-performance-wins-with-scalaz/
© 2022 - 2024 — McMap. All rights reserved.