-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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.