2016-08-18 66 views
0

我的問題:是否可以使用for-comprehension簡化這種嵌套式表達式?如何使用理解來表達以下嵌套式期貨

run(dbAction).flatMap(insertedJobs => { 
    Future.sequence(insertedJobs.map { job => 
    recordingBean.findStreamsForInterval(job.mediaSource, job.begin, job.end) map { stream => 
     if (stream.nonEmpty) { 
     recordingBean.findRecordingLocationsForInterval(stream.head.stream, job.begin, job.end).map(recordingLocations => 
      recordingLocations.map(_.size.getOrElse(0L)).sum).flatMap { expectedSizeInBytes => 
      updateSize(job.id.get, expectedSizeInBytes) 
     } 
     job 
     } else { 
     job 
     } 
    } 
    }) 
}) 
+1

你最好展示你的方法的類型或簡化你的問題。在這種形式中,你很難得到任何答案 – Nyavro

+0

你確定這段代碼有效嗎? –

+0

你有不匹配的括號。它不可能預測你想要什麼。 –

回答

1

爲了理解是強大的,但他們不是你認爲他們是全能的築巢殺手。

for-comprehension直到你沒有混合SeqLike monads與non-SeqLike monads是有用的。但是一旦你把它們混合在一起,你就回到了嵌套世界。而且它會比以前更糟,因爲理解會隱藏細節。

讓我們一些例子,

val listOfListOfInt = List(List(1, 2, 3), List(2, 3, 4)) 

val listOfInt = for { 
    loi <- listOfListOfInt 
    i <- loi 
} yield i + 4 

// This will work just fine 
// listOfInt: List[Int] = List(5, 6, 7, 6, 7, 8) 

現在讓混合ListFuture

val futureOfList = Future({ List(1, 2, 3) }) 

val iWillNotCompile = for { 
    l <- futureOfList 
    i <- list 
} yield i + 4 

// the above is equivalent to writing, 
val iWillNotCompile = futureOfList.flatMap(l => l.map(i => i + 4)) 

// would have been following but does not make sense 
// `Success(5, 6, 7)` 

上面的代碼將無法編譯,實際上它不應該編譯。由於Future是一個non-SeqLike monad。我的意思是,如果上面的代碼工作,它會是一個Success(5, 6, 7),這是沒有道理的。

同樣,下面的代碼將無法正常工作

​​

這種情況是從以前的一個很不一樣的,因爲它證實了常理,但它仍然是行不通的。原因在於SeqLike-MonadsFuture具有非常不同的實現flatMapflattenmap

所以...如果正在處理的ListFutureOptionTry等混合,從for-comprehension望而卻步。試着以更聰明的方式編寫代碼。

+0

展開:期貨實際上不是Monads。他們只有monad-like屬性。這有一個很好的討論http://stackoverflow.com/questions/27454798/is-future-in-scala-a-monad –

+0

是的。數學Scala「未來」可能會違反monad定義,因爲它們會帶來副作用。但是,純粹的monad討論屬於純函數式編程,其中副作用被視爲一種致命的罪。所以如果功能純粹主義者使用「未來」,他不會使用副作用,因此「未來」不會違反單子法。 –

+0

是否有可能使用某種語法糖來表達Future {}。map(a => a.map(b => b))如何結束? –