Conversation
test/core/QCheck2_expect_test.ml
Outdated
| @@ -481,8 +481,8 @@ module Function = struct | |||
| Gen.(quad (* string -> int -> string *) | |||
| (fun2 ~print:Print.string Observable.string Observable.int (small_string ~gen:char)) | |||
| (small_string ~gen:char) | |||
There was a problem hiding this comment.
also switch to string_small? (two occurrences)
test/core/QCheck2_expect_test.ml
Outdated
| ~print:Print.(triple (list int) Fn.print Fn.print) | ||
| Gen.(triple | ||
| (small_list small_int) | ||
| (small_list nat_small) |
test/core/QCheck2_expect_test.ml
Outdated
| let failing = | ||
| Test.make ~name:"should_fail_sort_id" ~count:10 ~print:Print.(list int) | ||
| Gen.(small_list small_int) (fun l -> l = List.sort compare l) | ||
| Gen.(small_list nat_small) (fun l -> l = List.sort compare l) |
src/core/QCheck2.ml
Outdated
| let int_small_signed : int t = fun st -> | ||
| if RS.bool st | ||
| then small_nat st | ||
| else (small_nat >|= Int.neg) st |
There was a problem hiding this comment.
Use nat_small? (two occurrences)
src/core/QCheck2.ml
Outdated
| let string_printable = string_size ~gen:printable nat | ||
|
|
||
| let small_string ?gen st = string_size ?gen small_nat st | ||
| let string_small ?gen st = string_size ?gen small_nat st |
src/core/QCheck2.ml
Outdated
| let small_string = string_small | ||
|
|
||
| let small_list gen = list_size small_nat gen | ||
| let list_small gen = list_size small_nat gen |
src/core/QCheck2.ml
Outdated
| let small_list = list_small | ||
|
|
||
| let small_array gen = array_size small_nat gen | ||
| let array_small gen = array_size small_nat gen |
src/core/QCheck2.mli
Outdated
| *) | ||
|
|
||
| val small_string : ?gen:char t -> string t | ||
| (** Builds a string generator, length is {!small_nat}. |
src/core/QCheck2.mli
Outdated
| @since 0.11 *) | ||
|
|
||
| val string_small : ?gen:char t -> string t | ||
| (** Builds a string generator, length is {!small_nat}. |
|
Thanks for taking a stab at this! Overall this LGTM 😀 I spotted a few occurrences of There's also one remaining in line 62 of the interface in the documentation example at the top: I'm guessing there are probably more that I missed. Looking at the new interface from a distance we still have a bit of inconsistency regarding signed generators: val int : int t
val pint : ?origin : int -> int t
val int_neg : int t
val int_small_signed : int t
val int_small_corners : unit -> int t
val int_pos_corners : int list
val int_corners : int listcompared to: val float : float t
val float_p : float t
val float_n : float tOne option would be to rename
but if the majority prefers The
@c-cube ? Finally, there's the "optional parameters that aren't so optional" that you didn't intend to address in this PR: |
There is most certainly other occurences, thanks for noticing (some of) them. I will correct them and have a second look.
I also do prefer
I think the way to go for optional parameters would be like @sir4ur0n mentioned:
But for instance with val opt : 'a t -> 'a option t
val opt_ratio : ratio:float -> 'a t -> 'a option tFor other types such as |
|
I think |
|
Regarding where |
I like I guess a second implicit design principle is to try to align generator names with OCaml's type names and type constructors:
To keep alignment with the types and type constructors I agree about the |
|
While addressing the suffixes and optional parameters (except |
So making The QCheck parallel is probably
An alternative would be to have an optional |
| val nat_origin : int -> int t | ||
| (** Generates non-strictly positive integers uniformly ([0] included). | ||
|
|
||
| Shrinks towards [origin] if specified, otherwise towards [0]. |
There was a problem hiding this comment.
[nat_origin b] shrinks towards [b].
| Shrinks towards [origin] if specified, otherwise towards [0]. *) | ||
| Shrinks towards [origin] if specified, otherwise towards [0]. | ||
|
|
||
| @deprecated use {!int_origin} *) |
|
not very fond of required+labeled in this case, but why not . Remember you also need a For |
|
|
||
| let option gen = option_ratio ~ratio:0.85 gen | ||
|
|
||
| let opt ?(ratio = 0.85) = option_ratio ~ratio |
There was a problem hiding this comment.
Does this compile without the dreaded "this-optional-argument-is-not-so-option" warning/error?
(I realize it is curried, so that option_ratio will expect a later gen argument)
There was a problem hiding this comment.
I did not have the warning but I will double check. But I think the gen argument should prevent the warning yes.
|
|
||
| let pint ?(origin : int = 0) : int t = fun st -> | ||
| let nat_origin origin : int t = fun st -> | ||
| let x = pint_raw st in |
There was a problem hiding this comment.
I suggest renaming pint_raw to nat_pos_raw while we are at it.
I know it isn't visible from the outside, however using the naming principles internally should make reading the implementation easier for ourselves and others going forward.
| if n <= (1 lsl 30) - 2 | ||
| then Tree.make_primitive (fun a () -> Shrink.int_towards 0 a ()) (RS.int st (n + 1)) | ||
| else Tree.map (fun r -> r mod (n + 1)) (pint st) | ||
| else Tree.map (fun r -> r mod (n + 1)) (nat st) |
There was a problem hiding this comment.
I think suspect this renaming introduces a bug: the else branch handles n bigger than 30-bit,
which will then need the old pint (now: nat_origin) to stitch together 3 calls.
Using plain nat outputs max 10.000 though. A statistics test should reveal the change in distribution!
This would be a good opportunity to add it 😀
| then nat_origin 0 >|= (fun n -> - n - 1) | ||
| else nat_origin 0 | ||
|
|
||
| let int_bound (n : int) : int t = |
There was a problem hiding this comment.
For consistency, should this really be called nat_bound? 😬
|
Hm. I'm starting to realize that this has opened a can of worms and wonder if the design is going in the direction we intend it to... In a sense, having val nat_origin : int -> int t
val nat_small : int t
val nat : int t
val nat_big : int tI noticed that
when comparing to these: val int : int t
val int_neg : int t
val int_small : int t
val int_small_corners : unit -> int t
val int_range : ?origin:int -> int -> int -> int t
val int_pos_corners : int list
val int_corners : int listSo we end up having |
This should be addressed yes, in this MR or in a subsequent one. If you want to add these new generators feel free to commit on my branch.
Would it make sense to have
It should also be addressed yes. |
|
I really wish I can revive this PR, however, I'm still busy and I will be for a while. Once I get the time that'll be the first thing I'll do :) |
|
Thanks for this renaming effort! 🙏 The new renaming effort is described in #366 Thanks again! |
Partially close #162 (the optional parameters are not adressed)
As QCheck2 is already released, I went with a "deprecated" phase, this can be back ported to QCheck1 as well.
The generator naming convention is basically
<type>_suffixeswhere_suffixesis optional.