代码之家  ›  专栏  ›  技术社区  ›  Slow Harry

如何表达以下嵌套的未来,以便于理解

  •  0
  • Slow Harry  · 技术社区  · 8 年前

    我的问题:为了便于理解,可以用简化这个嵌套表达式吗?

    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 回复  |  直到 8 年前
        1
  •  2
  •   sarveshseri    8 年前

    因为理解是强大的,但它们并不是你认为的万能的筑巢杀手。

    for-comprehension 在你不混合之前是有用的 SeqLike 单子 non-SeqLike 单子。但一旦你们把它们混在一起,你们就回到了筑巢的世界。这将比以前更糟,因为因为理解会掩盖细节。

    让我们举几个例子,

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

    上面的代码不会编译,实际上也不应该编译。像 将来 是一个 非SeqLike 莫纳德。我的意思是,如果上面的代码有效,它将是一个 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 将来 有非常不同的实现 flatMap flatten map .

    所以…如果要处理的是 列表 , 将来 , Option , Try 等等,远离 为了理解 。只需尝试用更聪明的方式编写代码。