【问题标题】:decoding scalacheck and scalatest code解码 scalacheck 和 scalatest 代码
【发布时间】:2023-03-17 15:14:02
【问题描述】:

我试图破译这实际上意味着什么

check { (n: Int) =>
  n > 1 ==> n / 2 > 0
}

来自http://www.scalatest.org/user_guide/writing_scalacheck_style_properties

我首先试图破译那具尸体是否是

((n: Int) => n > 1) ==> n/2 > 0

or

(n: Int) => (n > 1 ==> n/2 > 0)

会是哪一个?我猜是后者,因为尽管方法 '==>' 也可能返回一个函数,但 check 方法需要一个函数?

接下来看https://searchcode.com/codesearch/view/12336175/处的check方法签名

def check[A1,P](f: A1 => P)
  (implicit
     p: P => Prop,
     a1: Arbitrary[A1], s1: Shrink[A1]
  ) {
    check(Prop.property(f)(p, a1, s1))
}

我相信 A1 将是 Int 除非 ==> 返回一个函数并更改返回类型(尽管我认为这很可疑)。我不确定如何在 scalacheck 库中找到隐式函数 P => Prop。

我注意到有一个 ExtendedBoolean 有一个函数 ==> https://github.com/rickynils/scalacheck/blob/master/src/main/scala/org/scalacheck/Prop.scala

假设函数为 (n: Int) => (n > 1 ==> n/2 > 0),也许 (n > 1) 被转换为 ExtendedBoolean,然后我们得到 ​​p>

ExtendedBoolean( n > 1 ).==>( n / 2 > 0 ) is called then.

由于 ExtendedBoolean 的 ==> 的实现是 Prop(b) ==> p,所以我最终得到了

Prop( n > 1 ) ==> (n / 2 > 0)

我在这里真的很困惑,因为在按名称调用时,通常会捕获值,但此时 n 没有值,因为它最初是一个函数。暂时忽略我的困惑,因此 ==> for Prop 的实现是

def ==>(p: => Prop): Prop = flatMap { r1 =>
  if(r1.proved) p map { r2 => mergeRes(r1,r2,r2.status) }
  else if(!r1.success) Prop(r1.copy(status = Undecided))
  else p map { r2 => provedToTrue(mergeRes(r1,r2,r2.status)) }
}

所以,我们这样称呼它,所以我认为这里是 Prop 的另一个隐式版本

Prop( n > 1 ) ==> Prop(n / 2 > 0)

好的,平面图是

Prop(prms => f(this(prms))(prms))

hmmm,一定有另一个转换为 Prop 。我开始跟踪 prms,然后查看布尔值的对象 Prop 应用方法,它是

def apply(b: Boolean): Prop = if(b) proved else falsified

但我无法将 b 解析为 true 或 false,因为尚未评估这些函数。这一切如何协同工作?我想我在这里几乎没有遗漏一些概念。有人能解释一下吗?

【问题讨论】:

  • 您没有遗漏任何东西。 ExtendedBoolean 计算按名称参数def ==>(p: => Prop) = Prop(b) ==> p。 “按名称参数不在函数应用时进行评估,而是在函数内的每次使用时进行评估。也就是说,使用按名称调用来评估参数。”
  • 我习惯了 log4scala 之类的东西,其中 log.debug(=>String) 采用 log.debug("hi there "+name) 之类的东西,并且名称已经定义。在这种情况下,按名称接收的名称尚未定义。这甚至可能吗?在 log.debug 情况下,它会捕获闭包中 name 的值,以防以后对闭包进行评估(当然可能不会),但我在上面这段代码的上下文中没有得到它。

标签: scala scala-2.10


【解决方案1】:

您的问题确实是一个 ScalaCheck 问题,但避免整个问题的一种方法是使用 ScalaTest 的 PropertyChecks 语法而不是 ScalaCheck 的(在 ScalaTest 中由 Checkers 支持):

import org.scalatest.prop.Checkers._

check { (n: Int) =>
  n > 1 ==> n / 2 > 0
}

变成:

import org.scalatest.MustMatchers._
import org.scalatest.prop.PropertyChecks._

forAll { (n: Int) =>
  whenever (n > 1) {
    n / 2 must be > 0
  }
}

【讨论】:

  • 感谢您的回答,但我并不想回避这个问题。我正在努力增加我对scala的了解。我习惯了 log.debug(=> String) 之类的东西,我可以在其中传递“我的名字是”+name,并且名称被捕获为“dean”或其他东西。在上面的 scalacheck 示例中,n 还没有值。你真的可以将一个函数拆分成一个闭包,以后可能会像这样进行评估吗?还是我误读了代码。
猜你喜欢
  • 2015-11-21
  • 2014-03-17
  • 2016-05-20
  • 2014-12-29
  • 2017-01-14
  • 2018-05-08
  • 2015-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多