是否有可能以Either类似的方式处理Option?在Option,我有一个getOrElse功能,在Either我想要返回Left或处理Right.我正在寻找最快的方法,没有任何样板:
val myEither:Either[String, Object] = Right(new Object())
myEither match {
case Left(leftValue) => value
case Right(righValue) =>
"Success"
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*nov 16
在Scala 2.12中,
两者都是右偏,这意味着Right被认为是操作的默认情况.如果是Left,则map,flatMap等操作会返回Left值不变
所以你可以做到
myEither.map(_ => "Success").merge
Run Code Online (Sandbox Code Playgroud)
如果你发现它比它更具可读性fold.
你可以使用.fold:
scala> val r: Either[Int, String] = Right("hello")
r: Either[Int,String] = Right(hello)
scala> r.fold(_ => "got a left", _ => "Success")
res7: String = Success
scala> val l: Either[Int, String] = Left(1)
l: Either[Int,String] = Left(1)
scala> l.fold(_ => "got a left", _ => "Success")
res8: String = got a left
Run Code Online (Sandbox Code Playgroud)
编辑:
重新阅读你的问题,我不清楚你是否想要返回Left或另一个(在其他地方定义)的值
如果是前者,你可以传递identity给.fold,但这可能会将返回类型更改为Any:
scala> r.fold(identity, _ => "Success")
res9: Any = Success
Run Code Online (Sandbox Code Playgroud)
cchantep和Marth都是解决您眼前问题的好方法.但更广泛地说,很难将Either视为完全类似的东西Option,特别是在让你表达可理解的可能计算的序列时.要么有投影API(在cchantep的解决方案中使用),但它有点破碎.(要么用警卫,模式匹配或变量赋值进行理解,要么突破.)
FWIW,我写了一个库来解决这个问题.它使用此API扩充了Either .您为Eithers定义了"偏见"."右偏"意味着普通流(map,get等)由Right对象表示,而Left对象表示某种问题.(正确的偏见是常规的,但如果你愿意的话你也可以定义一个左偏见.)然后你可以把它Either当作一个Option; 它是一个完全类似的API.
import com.mchange.leftright.BiasedEither
import BiasedEither.RightBias._
val myEither:Either[String, Object] = ...
val o = myEither.getOrElse( "Substitute" )
Run Code Online (Sandbox Code Playgroud)
更有用的是,您现在可以将Either视为真正的scala monad,即使用flatMap,map,filter和for comprehension:
val myEither : Either[String, Point] = ???
val nextEither = myEither.map( _.x ) // Either[String,Int]
Run Code Online (Sandbox Code Playgroud)
要么
val myEither : Either[String, Point] = ???
def findGalaxyAtPoint( p : Point ) : Either[String,Galaxy] = ???
val locPopPair : Either[String, (Point, Long)] = {
for {
p <- myEither
g <- findGalaxyAtPoint( p )
} yield {
(p, g.population)
}
}
Run Code Online (Sandbox Code Playgroud)
如果所有处理步骤都成功,locPopPair将是一个Right[Long].如果出现任何问题,它将是第一个Left[String]遇到的问题.
它稍微复杂一点,但定义一个空令牌是个好主意.让我们看看上面对于理解的略微变化:
val locPopPair : Either[String, (Point, Long)] = {
for {
p <- myEither
g <- findGalaxyAtPoint( p ) if p.x > 1000
} yield {
(p, g.population)
}
}
Run Code Online (Sandbox Code Playgroud)
如果测试p.x > 1000失败会发生什么?我们想要返回一些Left表示"空"的东西,但是没有普遍适当的值(不是所有Left的都是Left[String].截至目前,会发生的是代码会抛出一个NoSuchElementException.但是我们可以自己指定一个空标记,如下:
import com.mchange.leftright.BiasedEither
val RightBias = BiasedEither.RightBias.withEmptyToken[String]("EMPTY")
import RightBias._
val myEither : Either[String, Point] = ???
def findGalaxyAtPoint( p : Point ) : Either[String,Galaxy] = ???
val locPopPair : Either[String, (Point, Long)] = {
for {
p <- myEither
g <- findGalaxyAtPoint( p ) if p.x > 1000
} yield {
(p, g.population)
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果p.x > 1000测试失败,会出现也不例外,locPopPair也只是Left("EMPTY").
| 归档时间: |
|
| 查看次数: |
11410 次 |
| 最近记录: |