在Scala中使用Either
的惯用方法是什么?例如,当使用Option
时,如果当前为orElse
,我可以使用None
方法获取下一个可选值。但是如何以同样的方式使用Either
?我没有找到类似orElse
的方法来链接Either(并且我知道使用这种方法并不是一个好主意,因为我们丢失了Left
值)
修改:实际上,我有一系列if-elseif-elseif-else
个表达式,每个表达式都返回Right
或Left
。我想重构我的代码,使其变得“更具功能性”。我可以将其替换为firstOption orElse secondOption orElse...
,如果它是Option
,但是如何在Either
使用?
答案 0 :(得分:9)
这方面有很长的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
,则map
和flatMap
等操作会使Left
值保持不变:
def doubled(i: Int) = i * 2
Right(42).map(doubled) // Right(84)
Left(42).map(doubled) // Left(42)
您可以在Either API上阅读更多内容。
答案 1 :(得分:1)
从Scala 2.13
开始,Either#orElse
可用(在Either
中使Scala 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 :(得分:0)
最接近的:
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)
如果您正在处理Try
:
Throwable
either1.toTry orElse either2.toTry
是的,在我看来,缺少orElse
是不一致的,因为Either
现在2.12是正偏向的,并且有getOrElse
方法。