我有一系列验证函数可返回Option [Problem](如果有),如果没有找到验证问题,则返回None。 我想编写一个调用每个验证函数的简单函数,停止并返回第一个非-none结果。
当然我可以在“java风格”中编写这个方法,但我想知道是否存在更好的方法。
修改
这是最初的Java解决方案:
validate01(arg);
validate02(arg);
validate03(arg);
...
每个方法在出现问题时都会抛出异常。在我写Scala的时候,我会远离异常。
答案 0 :(得分:6)
举个例子,假设我们要验证String
。我们的验证函数采用String
和验证器列表,这些验证器是String
到Option[Problem]
的函数。我们可以用这样的功能方式实现它:
def firstProblem(validators: List[String => Option[Problem]], s:String) =
validators.view.flatMap(_(s)).headOption
这会通过将每个验证函数应用于字符串并仅在Some
为结果时保留结果来创建新列表。然后我们采用此列表的第一个元素。由于调用view
,列表将仅在需要时计算。因此,一旦找到第一个问题,就不会再调用其他验证器。
答案 1 :(得分: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)
答案 2 :(得分: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
)