【问题标题】:Filtering inside for-comprehension with futures用期货过滤内部理解
【发布时间】:2016-11-08 09:39:55
【问题描述】:

我正在做这样的事情:

 (for { 
   data <- Future(getData)
   updated = makeChanges(data) if updated != data
   _ <- Future(saveUpdates(updated))
   _ <- Future(recordTransaction)
 } yield ()).recover { case e: NoSuchElementException => () }

当过滤器不满意时,它会通过抛出异常(不好)跳过剩余的两个步骤(好!),我必须在最后捕获并处理。使用异常进行流控制对我来说并不太优雅,我想知道是否有更好的方法来做到这一点,除了显而易见的 - 用 if 语句包装所有剩余的行:

   _ <- if(updated != data) Future(saveUpdates(updated)) else Future.successful(())
   _ <- if(updated != data) ...

【问题讨论】:

  • 如果您可以更改 makeChanges 以返回 (changed:Boolean, updated:Data) 的元组,您可以对其进行模式匹配并决定在哪种情况下采取哪种操作。它会让它更干净
  • @LouisF。不明白你的意思。我可以很容易地在updated != data 上进行模式匹配,但不知道如何使用它来使其更干净。将最后一段中的if ... else .. 替换为match ... case?

标签: scala future for-comprehension


【解决方案1】:

我认为您不能以这种方式避免使用 for 理解的流控制异常,您可以使用嵌套表达式而不是过滤器并手动处理条件,为 scala 提供它需要的返回类型以防万一不满意:

for {
  data <- Future(data)
  updated = makeChanges(data)
  res = {
    if (updated != data) Future.successful(())
    else for {
      _ <- Future(saveUpdates(updated))
      _ <- Future(recordTransaction)
    } yield ()
  }
} yield res

但是对于这个示例,我会采用简单的方法并放弃 for 理解,这会导致代码更具可读性(尽管您的实际用例可能更复杂):

Future(data).flatMap(d => {
  val updated = makeChanges(d)
  if(updated == d) Future.successful(())
  else Future(saveUpdates(updated)).map(_ => recordTransaction)
})

【讨论】:

  • 是的,我自己不是理解力的忠实粉丝,但在这种特殊情况下,我认为你的建议根本不是“更具可读性”:(如果有什么我不喜欢的话不仅仅是过度使用 for-comprehensions,而是过度嵌套。
猜你喜欢
  • 2019-07-21
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 2014-03-30
  • 2016-04-05
  • 2015-07-17
  • 1970-01-01
相关资源
最近更新 更多