我的问题是:有没有可能用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
}
}
})
})发布于 2016-08-19 01:03:50
因为理解是强大的,但它们并不是你所认为的全能的嵌套杀手。
for-comprehension很有用,直到你不把SeqLike monads和non-SeqLike monads混合在一起。但是一旦你将它们混合在一起,你就回到了嵌套的世界。而且它将比以前更糟糕,因为for-comprehensions隐藏了细节。
我们举几个例子,
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) 现在让我们混合使用List和Future,
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),这是没有意义的。
类似地,下面的代码将不起作用
val listOfFuture = List(Future({ 1 }), Future({ 2 }), Future({ 3 }) )
val iWillNotCompile = for {
f <- listOfFuture
i <- f
} yield i + 4
// this is equivalent to
val iWillNotCompile = listOfFuture.flatMap(f => f.map(i => i + 4)
// should have been following and it makes sense
// List(Success(5), Success(6), Success(7))这个案例与上一个案例有很大的不同,因为它确认了常识,但仍然不会起作用。原因是SeqLike-Monads和Future对flatMap、flatten和map有非常非常不同的实现。
所以..。如果你处理的是List、Future、Option、Try等的混合应用,那就远离for-comprehension。试着用一种更聪明的方式写你的代码。
https://stackoverflow.com/questions/39014981
复制相似问题