Scala处理缺少嵌套的Optionals

时间:2016-05-18 15:25:36

标签: scala

我们说我有一个对象A,它可能有一个Option B,它也可能引用另一个可选对象C(嵌套选项)

我已经看过几种访问C的方式,比如for-comprehension,模式匹配或flatMap这些看起来都很好看。但是,如果我必须返回某种错误消息或在BC丢失时抛出异常或提供cannot execute because B is missingC not set等消息,该怎么办?我只能回到(​​嘲笑):

if(a.b.isDefined)
{
   if(a.b.c.isDefined)
   {
           //do work
   }
   else throw new Exception1 //or call something other
}
else throw new OtherException //or do something other

我如何以功能或更流畅的方式处理?

3 个答案:

答案 0 :(得分:6)

您可以添加一种方法将Option转换为Try,如果值为无,则会失败。

implicit class OptionWrapper[T](val o: Option[T]) extends AnyVal {
    def tryGet(e: => Throwable): Try[T] = o match {
        case Some(x) => Success(x)
        case None => Failure(e)
    }   
}

然后你可以做

a.b.tryGet(new OtherException).flatMap(_.tryGet(new Exception1))

答案 1 :(得分:3)

您可以使用getOrElse[B >: A](default: ⇒ B): B

  a.b.getOrElse(throw new OtherException).c.getOrElse(throw new Exception1)

使用implicit包装和AnyVal优化(之前描述)是个好主意,但您的代码变得不那么可读。我认为更喜欢使用现有方法而不是每次都写包装器。

关于map,这里真的没用。如果您不需要抛出Exception,那就有意义了。

答案 2 :(得分:2)

而不是将Option转换为其他东西,我会这样做:

ggplot(dat2, aes(x = variable, y = value)) +
  stat_summary(geom = 'point', fun.y = 'mean', size = 2) +
  stat_summary(geom = 'errorbar', width = 0.2) +
  xlab(NULL) + 
  theme_bw()

简而言之,如果 b 已定义,那么map将允许您使用它,然后您可以使用 c 上的getOrElse返回它,否则抛出异常。 最后一个getOrElse适用于 b ,所以如果map返回 c 的实例,它将返回它,否则如果 b 未定义它会让你抛出一个异常。

我用Scalatest写了一个快速测试来证明它:

    def getC(a: A) = a.b.map { b1 =>
        b1.c.getOrElse {
            throw new UndefinedC
        }
    }.getOrElse {
        throw new UndefinedB
    }

编辑: 顺便说一句,Alexandr Dorokhin的答案比我的答案少,如果你在测试中使用它们就会通过。