Scala中的功能断言

时间:2013-04-12 11:26:50

标签: scala functional-programming assert

是否内置支持返回结果的断言?

执行此操作非常无效:

  def addPositive(a: Int, b: Int) = {
    assert(a > 0 && b > 0)
    a + b
  }

我宁愿做类似的事情:

  def addPositive(a: Int, b: Int) = 
    assert(a > 0 && b > 0)(a + b)

通过这种方式,我可以避免断言的命令性方面。 (后者不编译) 有类似的东西吗?

3 个答案:

答案 0 :(得分:15)

功能编程将函数视为纯数学函数(理想情况下)。那么数学的一种方式是说某个函数对某些参数不起作用并且必须爆炸?

Partial Functions

事实证明,Scala对这个概念有很好的支持:PartialFunction。 这是使用部分函数重写代码的方法:

val addPositive: PartialFunction[(Int, Int), Int] = {
  case (a, b) if a > 0 && b > 0 => a + b
}

这有几个好处:

如果使用错误的参数调用它,则会抛出MatchError异常。

addPositive(-1, 2) => Exception in thread "main" scala.MatchError: (-1,2) (of class scala.Tuple2$mcII$sp)

您实际上可以对函数的域进行采样,以检查某些值是否适合作为函数的参数:

addPositive.isDefinedAt(-1, 2) => false

如果您想将该函数应用于某些参数并获得结果或某个值表示失败,您可以lift将其返回Option

addPositive.lift(-1, 2) => None
addPositive.lift(1, 2) => Some(12)

您可以将其与其他函数组合以在无效参数的情况下提供后备:

val fallback: PartialFunction[(Int, Int), Int] = { case (a, b) => Int.MinValue }
val f = addPositive orElse fallback

f(-1, 2) => -2147483648

或以自定义方式处理错误:

val raiseError: PartialFunction[(Int, Int), Int] = {
  case (a, b) => throw new IllegalArgumentException(s"Cannot apply addPositive to arguments $a and $b")
}
val g = addPositive orElse raiseError

g(-1, 2) => Exception in thread "main" java.lang.IllegalArgumentException: Cannot apply addPositive to arguments -1 and 2

它适用于标准库:请参阅Seq.collectSeq.collectFirst

同样PartialFunction是一个普通的一元函数,所以你也继承了所有的函数操作。

这篇文章解释了Scala中非常优雅的部分功能:

Scala partial functions (without a PhD)

答案 1 :(得分:4)

你可以推出自己的实现:

def assert[T](cond: =>Boolean)(expr: =>T): T = {
  assert(cond)
  expr
}

你也可以使用选项类型来避免异常,但这意味着你以后必须对结果进行模式匹配:

def addPositive(a: Int, b: Int): Option[int] =
  if (a > 0 && b > 0) Some(a + b)
  else None

这可以通过与上面的assert变体类似的方式进行重构。

答案 2 :(得分:-5)

前置条件有require函数,几乎可以完成你想要的任务。你可以做到

def addPositive(a: Int, b: Int) = 
   require (a > 0 && b > 0, a + b)

scala.Predef有一部分,所以总是包含它们。参数(示例中为a+b)按名称传递,因此只有在条件不为真时才会执行。

requires始终处于激活状态,如果您希望能够将其停用,则可以使用assert进行停用,例如:

assert(a > 0 && b > 0, a + b)