doilux’s tech blog

ITに関する備忘録。 DDP : http://doiluxng.hatenablog.com/entry/2018/01/01/195409

Futureをネストしてハマった

あかんやつ

import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration

object Main extends App {

  Await.ready(test(), Duration.Inf)

  def test(): Future[Unit] = {
    for {
      a <- Future { 1 }
    } yield {
      for {
        b <- Future { Thread.sleep(10000); a }
      } yield {}
    }
  }
}

testの戻り値がFuture[Future[Unit]]になっているが、このバグをコンパイラが検知できず、内側のFutureの処理をまたずにプログラムが終了する。

  def test(): Future[Unit] = {
    val a = for {
    ...
    a
  }

一度変数に詰めればコンパイルエラーになる。

Error:(17, 5) type mismatch;
 found   : scala.concurrent.Future[scala.concurrent.Future[Unit]]
 required: scala.concurrent.Future[Unit]
    a

よって、こうした。

  def test(): Future[Unit] = {
    val a = for {
      a <- Future { 1 }
    } yield {
      for {
        b <- Future { Thread.sleep(10000); a }
      } yield {}
    }
    a.flatten
  }