Прежде всего, будьте осторожны, используя object Main extends App
. Я считаю, что его инициализация полей semanti c менее очевидна, чем обычный старый main
с семантикой строка за строкой:
object Main {
def main(args: Array[String]): Unit = {...}
}
Вероятно, это проблема NullPointerException
.
Обычно это можно исправить, внимательно проверив порядок инициализации полей и пометив некоторые (или все) val
как lazy
.
StackOverflowError
возникает из-за слишком глубоких сгенерированных данных структура.
Обычно, когда вы имеете дело с любым типом рекурсии, всегда учитывайте базовый случай , когда рекурсия должна остановиться, и шаг , который в конечном итоге приведет к базовый случай .
В вашем конкретном случае мы можем использовать Gen.sized
и Gen.resize
, которые отвечают за создание «больших» элементов (дополнительную информацию можно найти в документации для проверки и в Google) .
package com.dtci.data.anonymize.parquet
import java.nio.charset.StandardCharsets
import org.scalacheck.Gen
object Main extends App {
sealed trait Val
case class Bin(bytes: Array[Byte]) extends Val
object Bin {
def from_string(str: String): Bin = Bin(str.getBytes(StandardCharsets.UTF_8))
}
case class Row(flds: List[(String, Val)]) extends Val
val gen_bin = Gen.alphaStr.map(Bin.from_string)
val gen_field_name = Gen.alphaLowerStr
val gen_field = Gen.zip(gen_field_name, gen_val)
val gen_row = Gen.sized(size => Gen.resize(size / 2, Gen.nonEmptyListOf(gen_field).map(Row.apply)))
def gen_val: Gen[Val] = Gen.sized { size =>
if (size <= 0) {
gen_bin
} else {
Gen.oneOf(gen_bin, gen_row)
}
}
gen_row.sample.get.flds.foreach(fld => println(s"${fld._1} --> ${fld._2}"))
}