2013-11-24 121 views
0

我的代碼由許多scala.concurrent.Futures的援引阿卡演員在我的演員實現Scala的期貨空安全邏輯映射和flatmap

所以樣品返回代碼將是類似以下內容:

val ivResult: Future[Any] = ask(ivActor, ivId) 

// perform mapping is a function of type (Any) => Unit 
val ivMapping: Future[Unit] = ivResult.map(performingMapping) 

// erLookup is a function of type (Any) => Future[Any] 
val erResult: Future[Any] = ivResult.flatMap(erLookup) 

依此類推。代碼基本上由future.flatmap()。map()來執行彙總邏輯

我的問題是,我想要實現空安全邏輯,如果未來的結果爲null,那麼我們不會拋出NullPointerExceptions

顯然,我可以在每個函數中嵌入空安全檢查,但考慮到Scala強大的功能,這些看起來有點冗長。

所以,我在找找出是否有一個更優雅的方式做到這一點,可能使用implicits等

+11

只是不返回'null'作爲'T'的實例,返回'Option [T]'。 'grep -r「null」'在你的項目中並修復所有出現的'null'。如果你有一個返回'null'的第三方方法,用'Option'包裝它:'Option(thirdPartyMethod())'。 – senia

+0

我很好奇,看到你在執行那些performMapping和erLookup函數。 – hequ

回答

1

一個Future的結果已經預示它是否已成功完成。

正常情況下,在NPE上,您的代碼會炸燬,未來將失敗。

你在說,請不要讓我的代碼爆炸,可能有害的副作用。

所以你想要一個具有特殊故障狀態的警衛。

喜歡的東西:

scala> object DeadFuture extends Exception with NoStackTrace 
defined object DeadFuture 

scala> implicit class SafeFuture[A](val f: Future[A]) { 
    | def safeMap[B](m: A => B)(implicit x: ExecutionContext) = 
    | f.map { a: A => if (a == null) throw DeadFuture else m(a) }(x) 
    | def safeFlatMap[B](m: A => Future[B])(implicit x: ExecutionContext) = 
    | f.flatMap { a: A => if (a == null) (Future failed DeadFuture) else m(a) }(x) 
    | } 

然後

scala> case class Datum(i: Int) 
defined class Datum 

scala> def f(d: Datum): Int = 2 * d.i 
f: (d: Datum)Int 

scala> def g(d: Datum): Future[Int] = Future(2 * d.i) 
g: (d: Datum)scala.concurrent.Future[Int] 

scala> Future[Datum](null) safeMap f 
res1: scala.concurrent.Future[Int] = [email protected] 

scala> .value 
res3: Option[scala.util.Try[Int]] = Some(Failure(DeadFuture$)) 

scala> def g(d: Datum): Future[Int] = Future(2 * d.i) 
g: (d: Datum)scala.concurrent.Future[Int] 

scala> Future[Datum](null) safeFlatMap g 
res4: scala.concurrent.Future[Int] = [email protected] 

scala> .value 
res5: Option[scala.util.Try[Int]] = Some(Failure(DeadFuture$)) 

有可能是一個更好的方式來誘導轉換,使您保持對-內涵。

for (i <- safely(futureInt)) f(i)