While trying to learn the ScalaCheck tool, I wrote two versions of a Map generator (I know there is one of these built in, but this was an exercise).
It seems that genMap0
and genMap00
should be equivalent, and genMap00
is bit cleaner, but in fact genMap0
works, but genMap00
fails miserably.
The yield
is adorned with a println
that can be turned on to see what happening (just edit the speak
method), but even with this information I cannot say I really understand why the difference. This makes me think that another generator I try to write may also be flawed.
Can someone give a nice explanation of what is different between genMap0
and genMap00
?
import org.scalacheck._
import Arbitrary._
import Gen._
import Prop._
def speak(message: String): Unit = if (false) println(message)
lazy val genMap0: Gen[Map[Int, Int]] = for {
k <- arbitrary[Int]
v <- arbitrary[Int]
b <- arbitrary[Boolean]
m <- if (b) value(Map.empty[Int, Int]) else genMap0
} yield if (b) {
speak("false"); m
} else {
speak("true"); m.updated(k, v)
}
lazy val genMap00: Gen[Map[Int, Int]] = for {
k <- arbitrary[Int]
v <- arbitrary[Int]
m <- oneOf(Map.empty[Int, Int], genMap00)
} yield if (m.isEmpty) {
speak("empty:" + m); m
} else {
speak("not empty:" + m); m.updated(k, v)
}
val n = 5
for (i <- 1 to n; m <- genMap0.sample) println(m)
println("--------------")
for (i <- 1 to n; m <- genMap00.sample) println(m)
This is the output (genMap00
always generates the empty map):
scala -cp scalacheck_2.10-1.10.1.jar
...
// Exiting paste mode, now interpreting.
Map()
Map(1 -> 1, 1530546613 -> -1889740266, -187647534 -> 0)
Map()
Map(-1 -> 2039603804)
Map(646468221 -> 1)
--------------
Map()
Map()
Map()
Map()
Map()