Why the type checking are not worked on this two assign statements?

playground
The code is below:

import concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

var wait1: Future[Unit] = Future.successful(())

def someAsyncFuncOne(): Future[(Int, Int, Int)] =
  Future.successful((1, 2, 3))

def someAsyncFuncTwo(tup: (Int, Int, Int)): Future[Unit] =
  Future.successful(())

wait1 = someAsyncFuncOne().map { result => // line 12
  {
    someAsyncFuncTwo(result).map { _ =>
      ()
    }
  }
}

def handle(result: (Int, Int, Int)): Future[Unit] = {
  someAsyncFuncTwo(result).map { _ =>
    ()
  }
}

wait1 = someAsyncFuncOne().map { // line 26
  handle
}

val result = someAsyncFuncOne().map { 
  handle
}

wait1 = result

The type of result is Future[Future[Unit]] and the type of wait1 is Future[Unit]. Apparently, the assign statement wait = result can not be compiled, but why this two statements of line 12 and line26 can be compiled?

On line 12, it’s assigning to a Future[Unit], so the map function is T => Unit, and hence it’s simply discarding the non-unit value in the map function (IntelliJ and scalac will report a warning about a discarded non-unit value here).

On line 26, it looks like a limitation of the playground parser (IntelliJ and scalac will report a type error on that line).

1 Like

There is no warning in my intelij console.

You need to enable the “value discard” flag.
Basically, the code is being rewritten into:

wait1 = someAsyncFuncOne().map { result => // line 12
  {
    someAsyncFuncTwo(result).map { _ =>
      ()
    }
    ()
  }
}

It adds the () at the end, and “discards” the previous expression.
With Future this may not be a big deal, since the Future was still created and is running in the background.

1 Like

Thanks, it’s worked!

1 Like