scala中嵌套的“if”/“match”语句:更好的方法?

时间:2012-12-26 21:51:35

标签: scala if-statement

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

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

修改

这是最初的Java解决方案:

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

每个方法在出现问题时都会抛出异常。在我写Scala的时候,我会远离异常。

3 个答案:

答案 0 :(得分:6)

举个例子,假设我们要验证String。我们的验证函数采用String和验证器列表,这些验证器是StringOption[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
)
相关问题