I'm trying to get my head around the Iteratee library in Play 2.2.x. I'm writing a function that generates a stream of data which is expensive to compute. Here's the basic idea, replacing the expensive to compute part with a square:
def expensiveFunction(x: Int): Future[Int] = Future.successful(x * x)
def expensiveRange(start: Int, end: Int): Enumerator[Future[Int]] = {
Enumerator.enumerate(start to end).map(i => expensiveFunction(i))
}
If I call expensiveRange
I get an Enumerator[Future[Int]]
, which is not what I want since it seems not to take advantage of the explicit asynchrony of the Iteratee pattern. It seems I should be able to transform this into an Enumerator[Int]
which under the covers uses the futures I return instead of creating another layer of Future
.
Am I right in my thinking that transforming the result to Enumerator[Int]
is desirable? If so, what is the idiomatic way to do so?
You could convert Enumerator[Future[Int]]
to Enumerator[Int]
this way:
val enumF = Enumerator((1 to 10).map{Future(_)}:_*) // Enumerator[Future[Int]]
val enum = enumF &> Enumeratee.mapM(identity) // Enumerator[Int]
But you don't need this conversion since, as Travis Brown noted, you could rewrite your method like this:
def expensiveRange(start: Int, end: Int): Enumerator[Int] = {
Enumerator.enumerate(start to end) &> Enumeratee.mapM(expensiveFunction)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With