【问题标题】:Scala.Either orElse methodScala.Either orElse 方法
【发布时间】:2013-08-21 08:09:36
【问题描述】:

在 Scala 中使用 Either 的惯用方式是什么?例如,当使用Option 时,如果当前为None,我可以使用orElse 方法获取下一个可选值。但是如何以同样的方式使用Either?我没有找到像 orElse 这样的方法来链接 Either 的(而且我知道使用这种方法并不是一个好主意,因为我们丢失了 Left 值)

编辑:事实上,我有一系列if-elseif-elseif-else 表达式,每个表达式都返回RightLeft。我想重构我的代码,让它变得“更实用”。所以如果是Option我可以用firstOption orElse secondOption orElse...替换,但是这里怎么用Either呢?

【问题讨论】:

  • 您希望通过使用比 if-else 链“更具功能性”的构造获得什么?这只是一个练习,看看它会是什么样子,还是你有什么目标? (例如,更少的样板、更少的重复、更容易发现错误等?)

标签: scala either


【解决方案1】:

Scala 2.13 开始,Either#orElse 已经可用,(在EitherScala 2.12 中右偏之后):

Right(1) orElse Left(2) // Right(1)
Left(1) orElse Left(2)  // Left(2)
Left(1) orElse Left(2) orElse Right(3) // Right(3)

【讨论】:

    【解决方案2】:

    最接近的:

    Left(1).left.flatMap(_=>Left(2)).left.flatMap(_=>Left(3))
    res22: Either[Int, Nothing] = Left(3)
    
    Right(1).left.flatMap(_=>Left(2)).left.flatMap(_=>Left(3))
    res23: Either[Int, Int] = Right(1)
    

    如果您正在处理Throwable,请使用Try

    either1.toTry orElse either2.toTry
    

    是的,在我看来,缺少orElse 是不一致的,因为Either 现在2.12 是右偏的,并且有getOrElse 方法。

    【讨论】:

    • 既然Either 是右倾的,我认为添加orElse 的拉取请求会被接受。至少,我不明白为什么它不会。
    【解决方案3】:

    关于这个,discussion 已经很长了。目前,正如您所说,Either 是公正的(即左右被视为相同)。因此,如果调用orElse,不知道该怎么办?使其偏向正确会解决问题(正如Tony Morris 所说,这是一个错误)

    所以一些技巧是:使用 LeftProjection 或 RightProjection。 Right Projection 具有实用功能 map、flatMap、filter 等)

    val a:Either[String, Int]
    val b:Either[String, Int]
    
    for{
    x <- a.right //returns a RightProjection of a
    y <- b.right
    } yield (a,b)
    

    a.right.getOrElse(b.right)。另一种解决方案是建议here

    object Implicits {
        implicit def rightBiasEither[A, B](e: Either[A, B]): Either.RightProjection[A, B] = e.right
      }
    
    import Implicits._
    a.getOrElse(b).getOrElse(c)
    

    这样你就可以继续使用它作为 monad。


    更新

    在 Scala 2.12 之后,Either 是右偏的,这意味着 Right 被假定为默认情况下进行操作。如果是Left,则mapflatMap 等操作返回Left 值不变:

     def doubled(i: Int) = i * 2
     Right(42).map(doubled) // Right(84)
     Left(42).map(doubled)  // Left(42)
    

    您可以在Either API 上阅读更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-17
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      相关资源
      最近更新 更多