如何反转Option Monad的流量?

san*_*jib 8 scala scala-option

比方说,我有一堆"验证"函数,如果没有错误则返回None,否则返回Some(String)指定错误消息.像下面这样的东西......

def validate1:Option[String] 
def validate2:Option[String]
def validate3:Option[String]
Run Code Online (Sandbox Code Playgroud)

我将按顺序调用它们,一旦返回Some(String),我就会停止并返回相同的内容.如果它返回None,我会转到下一个,直到序列结束.如果所有这些都返回None,则返回None.

我想把它们粘在一起"表达".就像是 ...

for( a <- validate1; b <- validate2; c <- validate3) yield None;
Run Code Online (Sandbox Code Playgroud)

但是,Option完全与我想要的相反.它在None处停止,并以Some(String)跟随.

我怎样才能实现这样的目标?

Don*_*zie 17

您可以在Option上使用orElse方法将调用链接在一起

validate1 orElse validate2 orElse validate3
Run Code Online (Sandbox Code Playgroud)

或者你可以在转换为函数的验证方法集合上运行折叠

val vlist= List(validate1 _, validate2 _, validate3 _)

vlist.foldLeft(None: Option[String]) {(a, b) => if (a == None) b() else a}
Run Code Online (Sandbox Code Playgroud)

  • +1我甚至将这两个解决方案合并以获得更短且更易读的形式:l.foldLeft(无:Option [String]){(a,b)=> a orElse b()} (3认同)

Ste*_*eve 2

难道不能将迭代器组合在一起然后获取第一个元素吗?就像是:

scala> def validate1: Option[String] = {println("1"); None}
scala> def validate2: Option[String] = {println("2"); Some("error")}
scala> def validate3: Option[String] = {println("3"); None}
scala> (validate1.iterator ++ validate2.iterator ++ validate3.iterator).next
1
2
res5: String = error
Run Code Online (Sandbox Code Playgroud)

  • 我认为您不想删除“.iterator”调用 - 那么您将始终调用所有验证方法,而不是仅调用方法,直到其中一个方法返回错误。 (2认同)