-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
QCheck2.Gen: enforce naming consistency #223
base: main
Are you sure you want to change the base?
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also switch to string_small
? (two occurrences)
test/core/QCheck2_expect_test.ml
Outdated
@@ -420,7 +420,7 @@ module Function = struct | |||
Test.make ~name:"fail_pred_map_commute" ~count:100 ~long_factor:100 | |||
~print:Print.(triple (list int) Fn.print Fn.print) | |||
Gen.(triple | |||
(small_list small_int) | |||
(small_list nat_small) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use list_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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use list_small
?
src/core/QCheck2.ml
Outdated
let small_int = small_nat | ||
|
||
let small_signed_int : int t = fun st -> | ||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use nat_small
? (two occurrences)
src/core/QCheck2.ml
Outdated
@@ -685,11 +697,14 @@ module Gen = struct | |||
|
|||
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use nat_small
?
src/core/QCheck2.ml
Outdated
|
||
let small_list gen = list_size small_nat gen | ||
let list_small gen = list_size small_nat gen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
src/core/QCheck2.ml
Outdated
|
||
let small_array gen = array_size small_nat gen | ||
let array_small gen = array_size small_nat gen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
src/core/QCheck2.mli
Outdated
|
||
@since NEXT_RELEASE | ||
*) | ||
|
||
val small_string : ?gen:char t -> string t | ||
(** Builds a string generator, length is {!small_nat}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nat_small
?
src/core/QCheck2.mli
Outdated
@@ -319,11 +394,22 @@ module Gen : sig | |||
|
|||
@since 0.11 *) | |||
|
|||
val string_small : ?gen:char t -> string t | |||
(** Builds a string generator, length is {!small_nat}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nat_small
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 list compared to: val float : float t
val float_p : float t
val float_n : float t One 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 t For 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[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} *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use {!nat_origin}
not very fond of required+labeled in this case, but why not . Remember you also need a For |
let p = RS.float st 1. in | ||
if p < (1. -. ratio) | ||
then Tree.pure None | ||
else Tree.opt (gen st) | ||
|
||
let option gen = option_ratio ~ratio:0.85 gen | ||
|
||
let opt ?(ratio = 0.85) = option_ratio ~ratio |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not have the warning but I will double check. But I think the gen
argument should prevent the warning yes.
@@ -399,14 +412,16 @@ module Gen = struct | |||
let right = RS.bits st in | |||
left lor middle lor right | |||
|
|||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
|
||
let int_bound (n : int) : int t = | ||
if n < 0 then invalid_arg "Gen.int_bound"; | ||
fun st -> | ||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 pint ~origin:0 >|= (fun n -> - n - 1) | ||
else pint ~origin:0 | ||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 t I 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 list So 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 :) |
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>_suffixes
where_suffixes
is optional.