Scalaz提供了一个Validation
类,可以很容易地用函数式方法解决这类问题。Validation
在此 Stack Overflow 答案中有一个更详细的示例说明如何使用,但我也会在这里给出一个草图,以展示它在您的情况下如何工作。我将假设以下设置:
case class Wine(name: String, grapes: String, country: String)
case class ValidationError(name: String, msg: String)
现在我们可以编写几个验证方法(注意我使用的是 Scalaz 7):
import scalaz._, Scalaz._
def checkNonempty(v: String, name: String, msg: String) =
if (v.nonEmpty) v.successNel else ValidationError(name, msg).failNel
def checkDuplicate(v: String, name: String, msg: String) =
if (true) v.successNel else ValidationError(name, msg).failNel
当然,您应该将自己的重复检查添加到最后一行。然后我们可以将它们包装在一起:
def createWine(name: String, grape: String, country: String) = (
checkNonempty(name, "name", "Name not specified").flatMap(_ =>
checkDuplicate(name, "name",
"There already exists a wine with the name '%s'".format(name)
)
) |@|
checkNonempty(grape, "grape", "Grape not specified") |@|
checkNonempty(country, "country", "Country not specified")
)(Wine.apply)
现在如果我们写这样的东西:
val result: ValidationNEL[ValidationError, Wine] = createWine(
"Whatever Estates", "Whatever Grape", "U.S."
)
我们将获得一个成功值:
Success(Wine(Whatever Estates,Whatever Grape,U.S.))
但是如果我们给它无效的输入:
val result: ValidationNEL[ValidationError, Wine] = createWine(
"", "Some Grape", ""
)
我们将获得累积错误的列表:
Failure(
NonEmptyList(
ValidationError(name,Name not specified),
ValidationError(country,Country not specified)
)
)
当然,您也可以使用自己的验证逻辑,但是如果您正在做很多此类事情,那么使用像 Scalaz 这样的库可能是值得的。