Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flatten future inside yield

Tags:

scala

In the code below x is type Future[Future[Int]] and I need to flatten it to become Future[Int]. How is this possible?

   def times(a:Int, b:Int) = Future { a * b }

   val x = for {
     x1 <- Future { 1 }
     x2 <- Future { 2 }
   } yield {
      val future = times(x1,x2)
      future.map { result => result * 2 }
   }
like image 537
ps0604 Avatar asked Mar 12 '26 16:03

ps0604


1 Answers

Use the same for-comprehension. As times returns Future taking input x1 and x2. You can use same for-comprehension to extract the value out of the future.

def times(a:Int, b:Int) = Future { a * b }

val x = for {
  x1 <- Future { 1 }
  x2 <- Future { 2 }
  result <- times(x1,x2)
} yield (result * 2)

Remember for-comprehension is a syntactic sugar for flatMaps and one final map

The whole thing can be written as

Future { 1 }.flatMap { x1 => Future { 2 }.flatMap { x2 => times(x1, x2).map { result => result * 2 }}}

Warning: As you are creating data independent futures inline (inside the for-comprehension or inside the flatMap). These futures will execute sequentially.

As first and second futures are data independent. They can be executed parallelly if you have created them outside the for-comprehension or flatMap.

Flatten futures

Use flatMap to convert Future[Future[Int]] into Future[Int]

def times(a:Int, b:Int) = Future { a * b }

val x = (for {
  x1 <- Future { 1 }
  x2 <- Future { 2 }
} yield {
  val future = times(x1,x2)
  future.map { result => result * 2 }
}).flatMap(identity) // <--- notice flatMap here around the for-comprehension

For clarity above code can be re-written as

def times(a:Int, b:Int) = Future { a * b }

val x = for {
  x1 <- Future { 1 }
  x2 <- Future { 2 }
} yield times(x1,x2).map(_ * 2)

val finalResult = x.flatMap(identity)

Scala REPL

scala> :paste
// Entering paste mode (ctrl-D to finish)

def times(a:Int, b:Int) = Future { a * b }

    val x = for {
      x1 <- Future { 1 }
      x2 <- Future { 2 }
    } yield times(x1,x2).map(_ * 2)

    val finalResult = x.flatMap(x => x)


// Exiting paste mode, now interpreting.


scala> finalResult
res0: scala.concurrent.Future[Int] = Future(Success(4))
like image 83
pamu Avatar answered Mar 16 '26 09:03

pamu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!