alb*_*ins 1 monads scala list option-type
我遇到一种情况,我使用函数来模拟规则应用程序,每个函数返回应用时将采取的操作,或者,如果无法应用规则,则返回空列表。我有很多规则想按顺序和短路进行尝试。在我习惯的其他语言中,我会将空序列视为 false/None 并将它们与 链接起来orElse,如下所示:
def ruleOne(): Seq[Action] = ???
def ruleTwo(): Seq[Action] = ???
def ruleThree(): Seq[Action] = ???
def applyRules(): Seq[Action] = ruleOne().orElse(ruleTwo).orElse(ruleThree)
Run Code Online (Sandbox Code Playgroud)
然而,据我了解,这不会起作用,事实上,它会做一些超出我预期的事情。
我可以使用returnwhich 让我感觉不好,或者更糟糕的是,嵌套if语句。if let在这里本来会很棒,但 AFAICT Scala 没有。
这里惯用的方法是什么?
你在这里有不同的方法。其中之一是将 Seq 内的所有操作组合在一起(因此创建一个Seq[Seq[Action]]),然后使用find(它将返回与给定条件匹配的第一个元素)。因此,例如:
Seq(ruleOne, ruleTwo, ruleThree).find(_.nonEmpty).getOrElse(Seq.empty[Action])
Run Code Online (Sandbox Code Playgroud)
我不清楚您的域应用程序,但最后一个允许将方法生成的getOrElse转换为. 该方法虽然评估所有序列(无短路)。OptionfindSeq
另一种方法包括Seq使用模拟您使用 pimp 我的库/扩展方法的想法的方法来丰富orElse:
implicit class RichSeq[T](left: Seq[T]) {
def or(right: => Seq[T]): Seq[T] = if(left.isEmpty) { right } else { left }
}
Run Code Online (Sandbox Code Playgroud)
按名称参数启用短路评估。事实上,仅当左侧序列为空时才计算右侧序列。
Scala 3 对于这种抽象有更好的语法:
extension[T](left: Seq[T]){
def or(rigth: => Seq[T]): Seq[T] = if(left.nonEmpty) { left } else { rigth }
}
Run Code Online (Sandbox Code Playgroud)
这样你就可以调用:
ruleOne or ruleTwo or ruleThree
Run Code Online (Sandbox Code Playgroud)