Open jlink opened 1 month ago
The term filter is indeed ambiguous and should be replaced by a more distinct name that implies its intent more clearly. The include - exclude pair is a good candidate, but I also came across select - reject which works for me.
A thought provoking message:
Why do you think arbitrary and generator should exist as two separate interfaces? They map one to one - one arbitrary summon one generator and generator can always be wrapped in an arbitrary.
This anachronism is being copied from Haskell over and over but still no values outside of Haskell has been provided. In Haskell Arbitrary is a type class and Gen is a function for producing new values. Arbitrary exists at the type level for compiler to summon the right generator.
In Java or Kotlin - there're no type classes. Arbitrary is just an interface that adds you one more call to get what you want which is a Generator.
For me Arbitrary
is the abstraction that can be transformed and combined. The actual generation of values is done by the framework within a property's validation lifecycle. So Generator
could be hidden from the normal user; it's visible only for the rare cases where you want to generate data outside of a property validation.
Thinking of it, having sample()
and sampleStream()
would be enough and the actual Generator
would become an implementation detail.
The disadvantage of hiding the generator is that it's no longer possible to implement a fully working arbitrary outside the core module, because the generator hides some necessary details, e.g. how to create edge cases and how to do exhaustive generation. Bringing those details into Arbitrary would IMO make the interface too messy.
So the split of Arbitrary and Generator is a separation of concerns. The open question for me is if the concerns addressed in Generator should be public in the first place.
Arbitraries and generators are fundamental concepts; so is transforming them into other arbitraries. Jqwik 1 already has a well-working API for that, so I suggest keeping the API similar where appropriate and making it simpler where possible.
Arbitrary and Generator
Let's start with the two fundamental interfaces:
Differences to Jqwik 1
Arbitrary.generator()
no longer takes agenSize
: This parameter turned out to be of little use in most cases and made caching of generators much more difficult.Generator
- used to be calledRandomGenerator
- can now directly generate values throughgenerate(GenSource source)
method. The detour over aShrinkable
type is no longer necessary.The concept of
GenSource
, which is new, will be discussed in other issues.Standard Transformations
Mapping, filtering, flat-mapping etc. should work as before. The same is true for creating lists, sets etc. Thus, there'll be a couple of default methods in
Arbitrary
:Filter or Include / Exclude?
Since the term filter is somewhat ambiguous, a few libraries have switched to provide
include
,exclude
,filterIn
,filterOut
or similar clarifying terms. Is this a clarification or does it go against expectations?