Я вижу очень очевидную ошибку в scalacheck, так что если она действительно существует, я не вижу, как люди используют ее для рекурсивных структур данных.
Эта программа завершается с ошибкой StackOverflowError
до того, как scalacheck вступает во владение при построении значения Arbitrary
. Обратите внимание, что тип Tree
и генератор для Tree
s дословно взяты из это руководство по scalacheck.
package treegen
import org.scalacheck._
import Prop._
class TreeProperties extends Properties("Tree") {
trait Tree
case class Node(left: Tree, right: Tree) extends Tree
case class Leaf(x: Int) extends Tree
val ints = Gen.choose(-100, 100)
def leafs: Gen[Leaf] = for {
x <- ints
} yield Leaf(x)
def nodes: Gen[Node] = for {
left <- trees
right <- trees
} yield Node(left, right)
def trees: Gen[Tree] = Gen.oneOf(leafs, nodes)
implicit lazy val arbTree: Arbitrary[Tree] = Arbitrary(trees)
property("vacuous") = forAll { t: Tree => true }
}
object Main extends App {
(new TreeProperties).check
}
Что еще более странно, так это то, что изменения, которые не должны ни на что влиять, похоже, изменяют программу так, чтобы она работала. Например, если вы измените определение trees
на это, оно пройдет без проблем:
def trees: Gen[Tree] = for {
x <- Gen.oneOf(0, 1)
t <- if (x == 0) {leafs} else {nodes}
} yield t
Еще более странно, если вы измените структуру двоичного дерева так, чтобы значение сохранялось в Node
s, а не в Leaf
s, и измените определение leafs
и nodes
так:
def leafs: Gen[Leaf] = Gen.value(Leaf())
def nodes: Gen[Node] = for {
x <- ints // Note: be sure to ask for x first, or it'll StackOverflow later, inside scalacheck code!
left <- trees
right <- trees
} yield Node(left, right, x)
Он также тогда работает нормально.
Что тут происходит? Почему построение значения Arbitrary
изначально вызывает переполнение стека? Почему кажется, что генераторы scalacheck настолько чувствительны к незначительным изменениям, которые не должны влиять на поток управления генераторами?
Почему мое выражение выше с oneOf(0, 1)
точно не эквивалентно исходному oneOf(leafs, nodes)
?
trees
всегда оценивает оба аргумента, а тот, который используетif
, - нет? - person pedrofurla   schedule 07.11.2013oneOf
действительно строг: scalacheck.googlecode.com/svn/artifacts/1.7/doc/api/org/ - person pedrofurla   schedule 07.11.2013