我以这种方式存储错误代码及其字符串消息:
object Error {
def FileNotFound(filename: String) = Error("ERR01", s"${filename} not found")
def UserNotExist(userName: String) = Error("ERR02", s"${userName} not exist")
}
case class Error(code: String, value: String) {}
像这样保持它的好处是我可以将字符串值传递给错误消息。
我正在创建它
def validate(data: SomeType): List[Error] = {
var errors = ListBuffer[Error]()
if (validation1("abc") == false) {
errors+= Error.FileNotFound("abc")
}
if (validation2("lmn") == false) {
errors+= Error.UserNotExist("lmn")
}
errors.toList
}
我是Scala和函数式编程的新手。 这样写错误代码是正确的方法吗? 它遵循函数式编程范式吗?
scala:2.11
答案 0 :(得分:2)
这是我的两分钱,上面有一个完整的例子。
我假设您想以简单易用的功能样式进行此操作,因此让我们删除可变的ListBuffer
并了解如何处理。步骤的描述在代码之后。
更新:我想指出,在您的代码中,可以使用ListBuffer
,因为它不会破坏rerefential transparency。这是因为您不会在函数外部公开其可变性质,并且函数的输出仅取决于其输入。
尽管如此,我还是更倾向于避免使用可变数据,除非出于特殊原因,例如紧凑性或性能。
object StackOverflowAnswer {
/* Base type with some common fields */
class MyError( val code: String, val msg: String )
/* FileNotFound type, subtype of MyError, with its specific fields */
case class FileNotFound( filename: String ) extends MyError(
"ERR01", s"$filename not found"
)
/* UserDoesntExist type, subtype of MyError, with its specific fields */
case class UserDoesntExist( userName: String ) extends MyError(
"ERR01", s"$userName doesn't exist"
)
/*
* Validates the file. If it finds an error it returns a Some(MyError) with
* the error that's been found
* */
def checkForBadFile( data: String ): Option[MyError] =
if( data.contains("bad_file.txt") )
Some(FileNotFound("bad_file.txt"))
else
None
/*
* Validates the user. If it finds an error it returns a Some(MyError) with
* the error that's been found
* */
def checkForMissingUser( data: String ): Option[MyError] =
if( data.contains("bad_username") )
Some(UserDoesntExist("bad_username"))
else
None
/*
* Performs all the validations and returns a list with the errors.
*/
def validate( data: String ): List[MyError] = {
val fileCheck = checkForBadFile( data )
val userCheck = checkForMissingUser( data )
List( fileCheck, userCheck ).flatten
}
/* Run and test! */
def main( args: Array[String] ): Unit = {
val goodData = "This is a text"
val goodDataResult = validate( goodData ).map( _.msg )
println(s"The checks for '$goodData' returned: $goodDataResult")
val badFile = "This is a text with bad_file.txt"
val badFileResult = validate( badFile ).map( _.msg )
println(s"The checks for '$badFile' returned: $badFileResult")
val badUser = "This is a text with bad_username"
val badUserResult = validate( badUser ).map( _.msg )
println(s"The checks for '$badUser' returned: $badUserResult")
val badBoth = "This is a text with bad_file.txt and bad_username"
val badBothResult = validate( badBoth ).map( _.msg )
println(s"The checks for '$badBoth' returned: $badBothResult")
}
}
我开始为错误定义类型结构,类似于您。
然后,我有两个功能,可对所需的每张支票进行验证。当发现错误时,将使用Scala的Option类型返回错误。如果您不熟悉Option,可以看看at this link或进行一些谷歌搜索。
然后,我具有验证功能,该功能调用并存储上述每个检查。最后一点是使用flatten
(doc here),将List[Option[MyError]]
变平为List[MyError]
,除去中间的Option
。
然后有一些实际的代码为您展示了一些示例。