Reputation: 1949
Why does this scala code compile, The signature of recover is,
def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U]
then why does below code compile. You can see that recover
in below code doesn't return a Unit.
object TestRecover {
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
def failingFunction(input: Seq[String]): Future[Unit] = {
Future {
if (input.isEmpty) throw new Exception("Cannot be empty")
else ()
}
}
def callFailingFunc(input: Seq[String]): Future[Unit] = {
failingFunction(input).recover {
case _ =>
//Not returning Unit here, but Future[Unit]. Shouldn't type checker fail this ?
callFailingFunc(input.reverse)
}
}
}
Also why Await.result(TestRecover.callFailingFunc(Seq()), 20.seconds)
doesn't produce stackoverflow because of infinite recursion ?
Upvotes: 3
Views: 653
Reputation: 1066
then why does below code compile. You can see that recover in below code doesn't return a Unit.
The compiler is 'helping' you a bit and does an implicit conversion from Future[Unit]
to Unit
. Effectively compiling it like this.
def callFailingFunc(input: Seq[String]): Future[Unit] = {
failingFunction(input).recover {
case _ =>
//Not returning Unit here, but Future[Unit]. Shouldn't type checker fail this ?
callFailingFunc(input.reverse)
()
}
}
This blog explains is very nicely: http://blog.bruchez.name/2012/10/implicit-conversion-to-unit-type-in.html
Also why Await.result(TestRecover.callFailingFunc(Seq()), 20.seconds) doesn't produce stackoverflow because of infinite recursion ?
You don't get a stack overflow because every call to failingFunction
will create a new Future
with a new stack.
Upvotes: 3