4

我有一系列验证函数,如果没有发现验证问题,则返回 Option[Problem](如果有)或 None。我想编写一个简单的函数来调用每个验证函数,停止并返回第一个非无结果。

当然,我可以用“java-style”编写这个方法,但我想知道是否存在更好的方法。

编辑

这是最初的 Java 解决方案:

validate01(arg);
validate02(arg);
validate03(arg);
...

如果出现问题,每个方法都会引发异常。在编写 Scala 时,我会远离异常。

4

3 回答 3

6

例如,假设我们要验证一个String. 我们的验证函数接受一个String和一个验证器列表,它们是从String到的函数Option[Problem]。我们可以以这样的功能方式实现它:

def firstProblem(validators: List[String => Option[Problem]], s:String) =
  validators.view.flatMap(_(s)).headOption

这通过将每个验证函数应用于字符串并仅在结果为 时才保留结果来创建一个新列表Some。然后我们取这个 List 的第一个元素。由于调用view,列表将仅根据需要计算。因此,一旦发现第一个问题,就不会调用其他验证器。

于 2012-12-26T22:05:03.133 回答
6

如果您在编译时有有限且已知的验证次数,则可以在选项上使用 .orElse:

def foo(x: Int): Option[Problem] = ...
def bar(x: Int): Option[Problem] = ...
...
def baz(x: Int): Option[Problem] = ...


foo(1) orElse bar(2) orElse .. baz(n)
于 2012-12-26T22:06:04.533 回答
1

也许你想要——假设验证函数不带参数

def firstProblem(fs: (() => Option[Problem])*) = {
  fs.iterator.map(f => f()).find(_.isDefined).flatten
}

如果有的话,你会得到一个现有Option[Problem]的,或者None如果他们都成功了。如果您需要将参数传递给函数,那么您需要解释这些参数是什么。例如,您可以

def firstProblem[A](a: A)(fs: (A => Option[Problem])*) = /* TODO */

如果您可以将相同的参数传递给所有人。你会像这样使用它:

firstProblem(myData)(
  validatorA,
  validatorB,
  validatorC,
  validatorD
)
于 2012-12-26T22:08:33.717 回答