Fork me on GitHub

Hi, is it possible to restrict the range of values for integer predicates produced by the generator ? For example (malli.generator/generate [:int {:min 0 :max 6}]) reduces the range to [0,6], but (malli.generator/generate [int? {:min 0 :max 6}]) , where int? is an integer predicate, does not. My actual use case is with pos-int?. Thanks

Ben Sless15:10:33

pos-int? is equivalent to [:int {:min 1}] Type schemas are more flexible than predicate schemas

Ben Sless15:10:24

You can then add upper boundary with no complications


Excellent thanks! This is what I was looking for [:int {:min 0 :gen/max 10}] ; i.e. eq to nat-int? for validation and [0,10] for the generated range

Ben Sless16:10:45

Where types are concerned, I prefer the type schemas (with keywords) and not the predicate schemas

Ben Sless16:10:16

You use case is a perfect example why

Ben Sless15:10:34

When transforming multi to json schema, how about using implications?


Is there a generator option to produce distinct values for a vector? for example the following schema generated some values more than once

(->> [:vector {:min 400} string?]
       (filter (fn [[_ v]] (> v 1))))
;; => (["" 20] ["e" 2] ["7" 2])

Ben Sless03:10:44

Use a set generator then fmap vec


Great thanks! Although this has been a little bit of a mouthful it has done the trick:

[:vector {:min 400 
          :gen/schema [:set {:min 10} string?]
          :gen/fmap vec} 


(perhaps there should be a :gen/distinct option for collections? clojure.test.check.generators does seem to provide list-distinct and`vector-distinct` to this end)


This unfortunately does not scale very well, because I'd need to repeat the vector predicate twice, one for :vector the other for the generator's schema, which could easily get out of sync for more complicated schemas, e.g.

[:vector {:min 400
          :gen/schema [:set {:min 10} [:map [:x int?] [:y string?]]]
          :gen/fmap vec
         [:map [:x int?] [:y string?]]]

Ben Sless03:10:23

At that point you might want to define your own type and use a registry, you could call it distinct vector. Why does it need to be a vector, btw? Why can't it be. a set?


Hi, it has to be a vector because this is how values are coming out from the data source. The distinct values are only needed by the generator to produce some specific values during testing only. I can't seem to create a custom type with -simple-schema for distinct-vector ... The syntax of the type looks to be in accordance with the section on the readme file, but it gives me a :malli.core/invalid-schema {:schema (#object[cljs$core$string_QMARK_])} error when I try to use it ...

(let [vector-distinct
        (fn [_ schema]
          (let [schema (first schema)])
          {:type :vector-distinct
           :pred vector?
           {:gen/gen (clojure.test.check.generators/vector-distinct (malli.generator/generator schema))}}))]
  (-> [vector-distinct {} string?]

Ben Sless18:10:06

I think you want a variation on vector-of

Ben Sless18:10:20

the schema itself is incorrect, not the generation


sorry, not sure what you mean by "a variation on vector-of"; but I think I got it this time working, It appears I was missing the number of arguments accepted by the new type, in my case 1 (as in :min and :max):

(let [vector-distinct
         (fn [_ schema]
           (let [schema (first schema)]
             {:type ::vector-distinct
              :min 1
              :max 1
              :pred vector?
              {:gen/gen (clojure.test.check.generators/vector-distinct (malli.generator/generator schema))}})))]
    (->> [vector-distinct string?]
Does this look sane or is it just too hacky?


Actually that is not complete because pred is not going to check the vector values for conformity. I will stick with the following hack which almost does what I want (the only glitch is that generated distinct values are likely to be less than :min):

[:vector {:min 400 :max 400
          :gen/fmap #(into [] (set %))} string?]

Ben Sless07:10:29

ah, you need a collection schema, that's it