Fork me on GitHub
#clojure-spec
<
2020-03-10
>
ataggart12:03:11

Our tests are occationally failing with "Couldn't satisfy such-that predicate after 10 tries.", and the associated pred is `:pred #object[clojure.core\$ratio_QMARK_ 0x62fb2f00 "clojure.core\$ratio_QMARK_@62fb2f00"]`.

sogaiu12:03:10

there is some mention of such-that failures in gary fredericks' generators video at around 16:16 -- https://www.youtube.com/watch?v=F4VZPxLZUdA

gfredericks12:03:54

ratios are conceptually goofy because you may or may not want to consider integers to be ratios in a given context it's useful to think of integers as special kinds of ratios, because almost any use case for ratios should almost certainly apply to integers as well. It's hard to do arithmetic with ratios without bumping into integers inadvertently at least (e.g., `(* 3/4 4/3)`) but arguably it would surprise people if `(ratio? 42)` returned true, so it doesn't; maybe there are other good reasons for this too beyond just surprise in any case, there's a mismatch because test.check takes the first approach, but `ratio?` wearing its spec hat obviously has the same semantics as `ratio?` wearing its predicate hat, and so when you generate from it you don't want to generate integers I think `(such-that ratio? (ratio))` could definitely be improved; setting a higher retry threshold would stop the exceptions, but a custom generator would be the best; something like `(gen/let [[n d] (gen/tuple gen/large-integer gen/large-integer)] (let [r (/ n d)] (if (ratio? r) r (/ (inc n) d))))` there might be some arithmetical edge case there I'm not thinking of, but I think that works

ataggart13:03:11

Thanks for that! I thought I was losing my mind.

ataggart13:03:09

Perhaps spec'ing on `rational?` is the way I should go.

gfredericks12:03:07

also I forgot to handle `(zero? d)`