Welcome! Please see the About page for a little more info on how this works.

0 votes
in Spec by

The generator for any? will occasionally give back Double/NaN value(s). Since NaNs & equality (via =) don't get along, :ret spec'ing a fn which transforms/processes a collection according to a predicate, becomes rather problematic. That's because the most obvious thing to check under :ret (the case where the predicate didn't return true for any value, and so the output coll should be equal to the input coll because nothing was transformed/processed), cannot be expressed trivially.

The workaround I've come up with in my own specs is to spec the elements of the collection with (s/and any? (complement double-NaN?)) instead of just any?, and it works. However, even though I can live without NaNs in the tests, I must admit it still feels sort of hacky.


1) The generator for any? could be hardcoded to never return Double/NaN. Sounds rather invasive.
2) The generator for any? could be reworked to somehow be configurable wrt allowing/prohibiting Double/NaNs. Then perhaps a dynamic-var and/or a macro (e.g. without-NaNs) could expose this (just brainstorming here).
3) The generator for any? could stay as is, but a new equality operator could be added (e.g. clojure.spec/===`), which somehow ignores NaNs (a naive implementation for instance might walk the data-structures and replace all NaNs with keywords, and only then perform a regular comparison).

4 Answers

0 votes

Comment made by: alexmiller

Should consider whether this change is more appropriate in test.check or in the spec generator for any?.

0 votes

Comment made by: jimpil

It turns out that my workaround does not fully work. I literally just stumbled in the following case:

{nil {[] {NaN 0}}}

which is a conforming value for:

(s/def ::persistent-map
(s/map-of ::anything-but-NaN ::anything-but-NaN)) ;; (s/and any? (complement double-NaN?))

So basically, the inner collections can still have NaNs. So far I've got 4 specs that I've written and faced this problem on all of them. :(

0 votes

Comment made by: cap10morgan

{{exclude_NaN_from_any_and_some_generators.patch}} is my attempt at addressing this by preventing NaNs from appearing in any? and some? generated values. It seemed to solve the problem in my testing.

0 votes
Reference: https://clojure.atlassian.net/browse/CLJ-2054 (reported by jimpil)