是否可以与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"
}
答案 0 :(得分:15)
在Scala 2.12中,
所以你可以做到
myEither.map(_ => "Success").merge
如果您发现它比fold
更具可读性。
答案 1 :(得分:6)
您可以使用.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
答案 2 :(得分:5)
cchantep和Marth都是解决您眼前问题的好方法。但更广泛地说,很难将Either视为完全类似于Option
的东西,特别是在让你表达可理解的计算量序列时。要么有投影API(在cchantep的解决方案中使用),但它有点破碎。 (要么用警卫,模式匹配或变量赋值进行理解,要么突破。)
FWIW,我写了library来解决这个问题。它用this 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 comprehensions:
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")
。
答案 3 :(得分:2)
我猜你可以这样做。
def foo(myEither: Either[String, Object]) =
myEither.right.map(rightValue => "Success")
答案 4 :(得分:0)
在scala 2.13中,您可以使用myEither.getOrElse
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="Background" Value="Red" />
<Setter Property="Padding" Value="0" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>