2016-03-03 48 views
3

爲什麼這Scala代碼編譯, 恢復的簽名,然後從異常中恢復,斯卡拉未來

def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] 

爲什麼下面的代碼編譯。您可以在下面的代碼中看到recover未返回單元。

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) 
     } 
    } 
    } 

此外爲什麼Await.result(TestRecover.callFailingFunc(Seq()), 20.seconds)由於無限遞歸不產生計算器?

回答

3

那麼爲什麼下面的代碼編譯。你可以看到在下面的代碼中恢復不會返回一個Unit。

編譯器「幫助」了一下,並執行了從Future[Unit]Unit的隱式轉換。像這樣有效地編譯它。

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) 
    () 
    } 
} 

此博客解釋是非常漂亮:http://blog.bruchez.name/2012/10/implicit-conversion-to-unit-type-in.html

而且爲什麼Await.result(TestRecover.callFailingFunc(SEQ()),20.seconds)不會產生計算器因爲無限遞歸的?

您不會發生堆棧溢出,因爲每次調用failingFunction都會使用新的堆棧創建新的Future