Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ScalaCheck生成StackOverflower错误_Scala_Scalacheck - Fatal编程技术网

ScalaCheck生成StackOverflower错误

ScalaCheck生成StackOverflower错误,scala,scalacheck,Scala,Scalacheck,我想创建生成器(用于ScalaCheck)来生成命题公式。若我创建一个生成器来生成带有变量and和逻辑运算符(例如:a和B)的公式,那个么一切都是正确的。但如果我添加or,暗示而不是,ScalaCheck会生成异常:java.lang.StackOverflowerError import org.scalacheck.Prop import org.scalacheck.Properties import org.scalacheck.Gen object FormulaWffSpecifi

我想创建生成器(用于ScalaCheck)来生成命题公式。若我创建一个生成器来生成带有变量and和逻辑运算符(例如:a和B)的公式,那个么一切都是正确的。但如果我添加or,暗示而不是,ScalaCheck会生成
异常:java.lang.StackOverflowerError

import org.scalacheck.Prop
import org.scalacheck.Properties
import org.scalacheck.Gen

object FormulaWffSpecification extends Properties("FormulaWff") {

  abstract class FormulaWff {
    def size: Int
    def depths: Int
  }
  case class And(left: FormulaWff, right: FormulaWff)     extends FormulaWff
  case class Or(left: FormulaWff, right: FormulaWff)      extends FormulaWff
  case class Implies(left: FormulaWff, right: FormulaWff) extends FormulaWff
  case class Not(son: FormulaWff)                         extends FormulaWff
  case class Var(string: String)                          extends FormulaWff

  val genAnd = for {
    left  <- myGenFormula
    right <- myGenFormula
  } yield And(left, right)

  val genOr = for {
    left  <- myGenFormula
    right <- myGenFormula
  } yield Or(left, right)

  val genImplies = for {
    left  <- myGenFormula
    right <- myGenFormula
  } yield Implies(left, right)

  val genNot = for {
    son <- myGenFormula
  } yield Not(son)

  val genVar = Gen.oneOf(Var("A"),Var("B"))

  def myGenFormula: Gen[FormulaWff] =
    Gen.lzy(Gen.oneOf(genVar, genAnd, genImplies, genOr, genNot))

  property("size(t) <= 2^(depths(t) + 1) - 1") = {
    Prop.forAll(myGenFormula) { f: FormulaWff =>
      f.size <= Math.pow(2, f.depths + 1) - 1
    }
  }
}
import org.scalacheck.Prop
导入org.scalacheck.Properties
导入org.scalacheck.Gen
对象FormulaWff规范扩展属性(“FormulaWff”){
抽象类公式WFF{
定义大小:Int
定义深度:Int
}
案例类和(左:FormulaWff,右:FormulaWff)扩展了FormulaWff
案例类或(左:FormulaWff,右:FormulaWff)扩展了FormulaWff
case类暗示(左:FormulaWff,右:FormulaWff)扩展了FormulaWff
case类Not(子:FormulaWff)扩展了FormulaWff
case类Var(string:string)扩展了FormulaWff
val genAnd=用于{

左显而易见的直觉是
myGenFormula
的定义是递归的。这就是堆栈溢出的原因

解决此问题的一个部分是确保在
myGenFormula
的正确位置添加
Gen.lzy
。这确保执行生成器的单个路径,并避免不必要地执行所有递归生成器

myGenFormula
的定义存在第二个问题,这将导致堆栈溢出。如前所述,
myGenFormula
的定义在统计上不太可能终止。
genVar
生成器是终止生成器,但它与其他非终止生成器的权重相同。T这里没有什么可以阻止ScalaCheck在达到堆栈溢出之前生成无限深度的数据结构

有两种方法可以帮助递归生成器在ScalaCheck中终止。您可以使用
Gen.sized
将数字深度参数传递给生成器,也可以使用
Gen.frequency

相互递归生成器也存在初始化问题。您需要在引用
myGenFormula
的生成器
val
s上使用
lazy
关键字来避免此问题

这里有一个解决方案,它将
lazy
Gen.lzy
Gen.frequency
添加到您的代码中,以便它运行和终止。您可能需要根据您的测试需要进行调整

lazy val genAnd = for {
  left <- myGenFormula
  right <- myGenFormula
} yield And(left, right)

lazy val genOr = for {
  left <- myGenFormula
  right <- myGenFormula
} yield Or(left, right)

lazy val genImplies = for {
  left <- myGenFormula
  right <- myGenFormula
} yield Implies(left, right)

lazy val genNot = for {
  son <- myGenFormula
} yield Not(son)

val genVar =
  Gen.oneOf(Var("A"), Var("B"))

val myGenFormula: Gen[FormulaWff] =
  Gen.frequency(
    4 -> genVar,
    1 -> Gen.lzy(genAnd),
    1 -> Gen.lzy(genImplies),
    1 -> Gen.lzy(genOr),
    1 -> Gen.lzy(genNot))

property("myGenFormula") = {
  Prop.forAll(myGenFormula) { f: FormulaWff =>
    true
  }
}
lazy val genAnd=for{

左图这个答案解决了一个类似的问题,二叉树提出了类似的问题,但像这样的语法还有一些其他困难的障碍。