【问题标题】:Scala yield in case of success, but don't in case of exceptionScala在成功的情况下产生,但在异常的情况下不产生
【发布时间】:2014-07-12 03:39:46
【问题描述】:

我在 Scala 中有一个 Seq[T],并且想对每个元素做一些事情。在成功的情况下,我想将结果产生给用 for comprehension 创建的 Seq,但我不想产生任何异常情况。

我想要这样的东西:

val destinations = for(path <- files) {
  try {
    yield tryReadDestinations(path) 
  } catch {
    case _ => log.error("Error happened :(")
  }
}

但是这样的代码当然不能编译。我怎样才能实现这样的目标?

更新:

我设法得到这样的东西:

files
  .map(a => tryExtractDestinationsFromAttachment(a))
  .filter {
    case Success(d) => true
    case Failure(_) => false
  }
  .map(t => t.get)
  .flatten

tryExtractDestinationsFromAttachment 返回Try[String]

但我相信有可能让它更简单/更具可读性?

【问题讨论】:

  • 你期待什么结果?在成功的情况下收集结果,在任何时候失败的情况下,原因是什么? (全部或全部)?

标签: scala pattern-matching yield


【解决方案1】:

这就是你要找的吗?

import scala.util.{Try, Success, Failure}

def extractDestinationsFromAttachment(path: Path): Seq[Destination] = ???

val destinations = files flatMap { path =>
  Try(extractDestinationsFromAttachment(path)) match {
    case Success(dests) => dests
    case Failure(exception) => { log(exception); Nil }
  }
}

所有extractDestinationsFromAttachment 所要做的就是在失败时抛出带有错误消息的异常,或者在成功时抛出目标Seq

【讨论】:

    【解决方案2】:

    您可以将每次读取包装在 Try 中并执行以下操作:

    files
        .map(f => Try(tryReadDestinations(f)))
        .map(t => t.recoverWith { case ex => log.error(ex); t })
        .flatMap(_.toOption)
    

    【讨论】:

    • 我不想忽略错误,因为我需要记录它们。
    • 你可以flatMap SeqEitherleft 结果是抛出的异常,right 结果是正常值。
    • 引入视图或迭代器是有意义的,这样集合就不会被遍历 3 次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-07
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    相关资源
    最近更新 更多