是否有可能以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" }
Alexey Roman.. 16
在Scala 2.12中,
两者都是右偏,这意味着Right被认为是操作的默认情况.如果是Left,则map,flatMap等操作会返回Left值不变
所以你可以做到
myEither.map(_ => "Success").merge
如果你发现它比它更具可读性fold
.
在Scala 2.12中,
两者都是右偏,这意味着Right被认为是操作的默认情况.如果是Left,则map,flatMap等操作会返回Left值不变
所以你可以做到
myEither.map(_ => "Success").merge
如果你发现它比它更具可读性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
编辑:
重新阅读你的问题,我不清楚你是否想要返回Left
或另一个(在其他地方定义)的值
如果是前者,你可以传递identity
给.fold
,但这可能会将返回类型更改为Any
:
scala> r.fold(identity, _ => "Success") res9: Any = Success
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" )
更有用的是,您现在可以将Either视为真正的scala monad,即使用flatMap,map,filter和for comprehension:
val myEither : Either[String, Point] = ??? val nextEither = myEither.map( _.x ) // Either[String,Int]
要么
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) } }
如果所有处理步骤都成功,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) } }
如果测试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) } }
现在,如果p.x > 1000
测试失败,会出现也不例外,locPopPair
也只是Left("EMPTY")
.