当前位置:  开发笔记 > 编程语言 > 正文

Scala地图右或返回左

如何解决《Scala地图右或返回左》经验,为你挑选了3个好方法。

是否有可能以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.



1> Alexey Roman..:

在Scala 2.12中,

两者都是右偏,这意味着Right被认为是操作的默认情况.如果是Left,则map,flatMap等操作会返回Left值不变

所以你可以做到

myEither.map(_ => "Success").merge

如果你发现它比它更具可读性fold.



2> Marth..:

你可以使用.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



3> Steve Waldma..:

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").

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有