Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to produce an Enumerator[T] given Enumerator[Future[T]]

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?

like image 670
anelson Avatar asked Jan 05 '14 08:01

anelson


1 Answers

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)
}
like image 62
senia Avatar answered Oct 27 '22 00:10

senia