2

我喜欢使用require, assert,assume和 ensure 来记录给定函数的前置条件和后置条件,但我也开始scalaz.Validation主要用于执行需要执行的检查。但是,最近,我对使用PartialFunction(可能与Validation)来记录前置条件最感兴趣。就像是:

case class Summary(user: String, at: DateTime, ....)

val restricted_add: PartialFunction[(Summary, Summary), Summary] = {
  case (s1: Summary, s2: Summary) if s1.user != s2.user && s1.at == s2.at =>    

}

具有用于捕获匹配错误并将其转换为验证失败的实用程序功能(例如restricted_add.lift(_).toSucess("Cannot add."))。不知何故,上面的 case 子句似乎没有Forwith嘈杂scalaz.Validation。但我觉得我在反对这种语言。我没有使用def's 自然语法来定义参数,这样一个函数的每个客户端在调用它时都必须使用一个实用函数,我将捕获异常并将它们转换为验证,而不是仅使用验证或仅使用例外。

通过代码记录这些前提条件的最不嘈杂、最实用的方法是什么?Validation返回函数、require语句PartialFunction、其他...?

4

1 回答 1

1

正如@RandallSchulz 已经说过的,在代码中隐式记录先决条件仅适用于您的私有/内部方法,而不适用于您的公共 API。如果您正在编写公共方法,您还应该记录方法文档中的先决条件,也许还有使用示例,如果它们违反直觉的话。


话虽如此,在我看来,Scala 中噪音最小功能最强大的方式并不相同。这是因为require 不能被认为是功能性的,因为如果不满足条件,它会抛出异常,这将在某处被捕获,从而更改控制流并因此产生副作用。

尽管如此,我认为这require是迄今为止指定先决条件的最不嘈杂的方式:

def non_func(x:Int, y:Int):Int = {
    require(x >= 0 && y >= 0)
    x + y
}

我不完全确定检查先决条件的最实用方法,但我认为使用模式匹配并返回一个Option可以被认为是功能性的,但比require

def func(x:Int, y:Int):Option[Int] = (x,y) match {
    case (x, y) if x >= 0 && y >= 0 => Some(x + y)
    case _ => None
}

使用 Option 的好处是你可以对那个狗屎 (scnr)进行平面映射:

val xs = List((1,2), (0,0), (-1,0), (-1,-1), (3,4))
xs.flatMap(x => func(x._1, x._2)) # => List(3, 0, 7)

单独的可能是一个足够好的理由来添加更多的噪音,require因为它使您能够更简洁地使用许多标准 Scala 库。

关于偏函数,您基本上是在回答您自己的问题,因为您说使用和定义它更麻烦。不过,我对 Scalaz 没有任何经验,因此我无法将“纯 scala”方法与任何人可能使用 Scalaz 做的任何事情进行比较。

于 2013-04-02T08:37:10.500 回答