Reputation: 1897
My question: is it possible to simplify this nested expression with 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
}
}
})
})
Upvotes: 0
Views: 747
Reputation: 13985
For comprehensions are powerful but they are not an almighty nesting-killer you think they are.
for-comprehension
are useful till you are not mixing SeqLike
monads with non-SeqLike
monads. But once you mix them, you are back to nesting world. And it will be even worse than before because for-comprehensions hide away the details.
Lets take some examples,
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)
Now lets mix List
with 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)`
The above code will not compile and actually it should not compile. As Future
is a non-SeqLike
monad. I mean, if the above code worked it would have been a Success(5, 6, 7)
, which does not make sense.
Similarly, following code will not work
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))
This case is a lot different from the previous one, as it confirms to common sense but still it will not work. The reason is that SeqLike-Monads
and Future
s have very very different implementations of flatMap
and flatten
and map
.
So... if are dealing with a mix of List
, Future
, Option
, Try
etc, stay away from for-comprehension
. Just try to write your code in a more clever way.
Upvotes: 2