替代

2015-11-27 108 views
2

我想在斯卡拉使用alternativeEither[A, B]替代

这就是我想出了:

scala> val x: Either[String, Int] = Left("Foo") 
x: Either[String,Int] = Left(Foo) 

scala> val y: Either[String, Int] = Right(5555) 
y: Either[String,Int] = Right(5555) 

scala> x.fold(_ => y, _ => x) 
res1: Either[String,Int] = Right(5555) 

只使用标准库时,这是惯用的做法?

我担心的是我会有相当数量的fold's,因为我使用了超过2 Either's。

+1

我不知道你想acomplish但'x.left.flatMap(_ => y)等什么'似乎等价的,如果它满足你不能确定。 –

回答

2

也许一些拉皮条:

implicit class EitherOps[A,B] (x: Either[A,B]) { 
    def orElse (y: => Either[A,B]) = x.fold(_ => y, _ => x) 
} 
x orElse y orElse z 

请记住,它丢弃了所有可能的Left小号除了最后一个(如您的示例代码太)。

(更新:与通按姓名由Odomontois在评论建议)

+1

在这样的方法中使用pass-by-name参数更具惯用性,因为'y'值并不总是被使用。 – Odomontois

+0

@Odomontois - 你会考虑使用'Function0 [[A,B]]而不是'pass-by-name'吗? –

+0

@KevinMeredith这并不意味着你不得不这样做:''或者ELSE(()=> y)或者ELSE((=> z)' –

1

也许这样的事情,这需要任意数量的Either[] ARGS。仅当所有参数符合相同类型的配置文件时才保留类型信息。

def firstRight[A,B](args:Either[A,B]*):Either[A,B] = args match { 
    case Right(x)  +: _ => Right(x) 
    case Seq(Left(x))   => Left(x) 
    case _   +: tail => firstRight(tail: _*) 
} 
+0

IMO它有不必要的类型信息丢失。可能'不管[A,B]'是更实际的结果类型。 – Odomontois

+0

是的,在思考之后我同意。我相应地修改了它。 – jwvh

+0

这很好,但它在函数定义中缺少类型参数 – Odomontois