如何(最好)将选项转换为试用?

Sha*_*nds 19 scala scala-option

如何(最好)将方法调用返回的选项转换为Try(优先级,尽管Either或scalaz \/甚至验证可能没问题),包括在适当的情况下指定Failure值?

例如,我有以下代码,感觉很笨,但至少做(大部分)工作:

import scala.util._

case class ARef(value: String)
case class BRef(value: String)
case class A(ref: ARef, bRef: BRef)
class MismatchException(msg: String) extends RuntimeException(msg)

trait MyTry {

  // Given:
  val validBRefs: List[BRef]

  // Want to go from an Option[A] (obtained, eg., via a function call passing a provided ARef)
  // to a Try[BRef], where the b-ref needs to be checked against the above list of BRefs or fail:

  def getValidBRefForReferencedA(aRef: ARef): Try[BRef] = {

    val abRef = for {
      a <- get[A](aRef) // Some function that returns an Option[A]
      abRef = a.bRef
      _ <- validBRefs.find(_ == abRef)
    } yield (abRef)

    abRef match {
      case Some(bRef) => Success(bRef)
      case None => Failure(new MismatchException("No B found matching A's B-ref"))
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

感觉应该有一种方法可以将最终的比赛变成地图或平面地图或类似的结构,并将其纳入理解的前提.

此外,如果从BRef返回选项[A]的调用失败(返回None)与BRef检查失败相比,我希望能够指定不同的失败消息(我只关心知道失败的原因,所以scalaz验证感觉不是理想的合适).

这是一个使用monad变压器的合适场所吗?如果是这样,scalaz是否提供了合适的,或者有人可以举例说明它会是什么样子?

Jas*_*onG 12

您可以使用隐式转换

  implicit class OptionOps[A](opt: Option[A]) {

    def toTry(msg: String): Try[A] = {
      opt
        .map(Success(_))
        .getOrElse(Failure(new NoSuchElementException(msg)))
    }
  }
Run Code Online (Sandbox Code Playgroud)

Scala标准库使用这种方法.见http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html#companion-objects-of-a-type


cmb*_*ter 7

如果您Try从for-comp开始使用for-comp,那么您可以在最后消除匹配.您可以通过强制这样做OptionTry通过fold.这可能是这样的:

def getValidBRefForReferencedA(aRef: ARef): Try[BRef] = {
  for {
    a <- get[A](aRef).fold[Try[A]](Failure[A](new OtherException("Invalid aRef supplied")))(Success(_))
    abRef = a.bRef
    _ <- validBRefs.find(_ == abRef).fold[Try[BRef]](Failure(new MismatchException("No B found matching A's B-ref")))(Success(_))
  } yield abRef
}
Run Code Online (Sandbox Code Playgroud)

使用此方法,您可以为两个不同的检查获得不同的异常.它并不完美,但它可能适合你.


Min*_*uca 7

myOption
  .toRight(new Exception("y"))
  .toTry
Run Code Online (Sandbox Code Playgroud)

此代码将返回Success(x)if myOptionisSome(x)Failure(Exception("y"))if it is a None


Ata*_*ais 5

简短而简单

Try(option.get)
Run Code Online (Sandbox Code Playgroud)

无需花哨的映射。如果该选项为空,则会出现如下错误:

java.util.NoSuchElementException: None.get
Run Code Online (Sandbox Code Playgroud)

  • 除了依赖Try机制以及引发异常而不只是转换值之外。这是低效的。 (2认同)