7

我经常使用下面的函数来转换Option[Try[_]]Try[Option[_]]但感觉不对。可以用更惯用的方式表达这样的功能吗?

def swap[T](optTry: Option[Try[T]]): Try[Option[T]] = {
  optTry match {
    case Some(Success(t)) => Success(Some(t))
    case Some(Failure(e)) => Failure(e)
    case None => Success(None)
  }
}

假设我有两个值:

val v1: Int = ???
val v2: Option[Int] = ???

我想对这些值进行操作op(可能会失败)并将其传递给f下面的函数。

def op(x: Int): Try[String]
def f(x: String, y: Option[String]): Unit

我通常用于理解可读性:

for {
  opedV1 <- op(v1)
  opedV2 <- swap(v2.map(op))
} f(opedV1, opedV2)

PS。我想避免一些沉重的东西,比如scalaz。

4

3 回答 3

7

库允许您非常轻松地对一个序列进行排序:OptionTry

scala> import cats.implicits._
import cats.implicits._

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

scala> Option(Success(1)).sequence[Try, Int]
res0: scala.util.Try[Option[Int]] = Success(Some(1))

scala> Option(Failure[Int](new IllegalArgumentException("nonpositive integer"))).sequence[Try, Int]
res1: scala.util.Try[Option[Int]] = Failure(java.lang.IllegalArgumentException: nonpositive integer)

scala> None.sequence[Try, Int]
res2: scala.util.Try[Option[Int]] = Success(None)
于 2016-11-03T14:28:32.807 回答
4

听起来Try { option.map(_.get) }会做你想做的事。

于 2016-04-18T18:26:21.190 回答
1

此变体避免重新抛出:

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

def swap[T](optTry: Option[Try[T]]): Try[Option[T]] =
  optTry.map(_.map(Some.apply)).getOrElse(Success(None))

swap(Some(Success(1)))
// res0: scala.util.Try[Option[Int]] = Success(Some(1))

swap(Some(Failure(new IllegalStateException("test"))))
// res1: scala.util.Try[Option[Nothing]] = Failure(java.lang.IllegalStateException: test)

swap(None)
// res2: scala.util.Try[Option[Nothing]] = Success(None)
于 2016-04-18T22:17:24.097 回答