如何删除我的尝试的内部选项

时间:2016-11-03 15:19:38

标签: scala

如何删除该选项,使其仅为Try[Int]而非Try[Option[Int]]

val m = Map("a" -> "1a", "b" -> "2")
Try(m.get("a").map(_.trim.toInt))
>>es17: scala.util.Try[Option[Int]] = Failure(java.lang.NumberFormatException: For input string: "1a")

2 个答案:

答案 0 :(得分:7)

Map#get会返回Option[String],但在这种情况下,您可以使用Map#apply代替String

scala> Try(m("a").trim.toInt)
res3: scala.util.Try[Int] = Failure(java.lang.NumberFormatException: For input string: "1a")

scala> Try(m("b").trim.toInt)
res4: scala.util.Try[Int] = Success(2)
如果您要查找的密钥不存在,

apply会抛出异常,但无论如何Try都会抓住它。

答案 1 :(得分:1)

这个答案更详细地说明了评论:

  

我想知道是否有办法使用flapmap?您的解决方案适合我,只想了解其他替代方案。

正如您可能听到的那样,OptionTry是monad实例,而monad可以方便地表示计算序列,但它们不会与其他monad组合。换句话说,我们无法撰写OptionTry。我们需要找到一个共同点。

OptionTry之间的语义差异在于Try包含有关结果不存在时的情况的信息。

我们可以使用TryOption转到Try#toOption,有效地删除我们可能遇到的任何失败信息。

如果我们想要反过来,我们需要添加这些信息:当Option中没有值时,需要提供失败原因。像这样:

import scala.util.{Try, Success, Failure}
def optionToTry[T](opt:Option[T], failure: => Throwable): Try[T] = opt match {
  case Some(v) => Success(v)
  case None => Failure(failure)
}

在该函数的帮助下,我们可以将原始表达式重写为:

val res: Try[Int] = for {
  strValue <- optionToTry(m.get("a"), new NoSuchElementException("a"))
  value <- Try(strValue.trim.toInt)
} yield value

在后台使用flatMap组成这两个Try个实例:

val res = optionToTry(m.get("a"), new NoSuchElementException("a"))
                     .flatMap(strValue => Try(strValue.trim.toInt))

请注意,我们可以使用不安全的地图getter来节省一些编码:

val res: Try[Int] = for {
  strValue <- Try(m("a"))
  value <- Try(strValue.trim.toInt)
} yield value

但考虑到在JVM中处理异常的成本,这个版本的计算成本会更高。