Fork me on GitHub
#malli
<
2021-10-16
>
chaos15:10:41

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

chaos16:10:25

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? https://json-schema.org/understanding-json-schema/reference/conditionals.html#id7

2
chaos20:10:25

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?]
       malli.generator/generate 
       frequencies
       (filter (fn [[_ v]] (> v 1))))
;; => (["" 20] ["e" 2] ["7" 2])
Thanks

Ben Sless03:10:44

Use a set generator then fmap vec

chaos07:10:42

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} 
         string?]

chaos07:10:52

(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)

chaos21:10:09

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?

chaos17:10:45

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
      (malli.core/-simple-schema
        (fn [_ schema]
          (let [schema (first schema)])
          {:type :vector-distinct
           :pred vector?
           :type-properties
           {:gen/gen (clojure.test.check.generators/vector-distinct (malli.generator/generator schema))}}))]
  (-> [vector-distinct {} string?]
      malli.generator/generate))
Thanks!

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

chaos19:10:43

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

chaos06:10:07

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