malli 2024-09-27

how can I have values of multiple fields be generated with a shared generator function? for example, I have a data that looks like below.

[:map [:a int?] [:b int?] [:c int?]}
and the values of a, b, c have to differ by only one. so perhaps a generator should generate one random integer, make two more with each of them 1 greater, and allocate those to the keys a,b and c.

I think it's simplest to just add a :gen/gen to the :map and write the generator yourself

Yea but the generator has to generate values for separate keys at once. Otherwise the values will be generated independently

yes, that's why you attach it to the :map level, not the individual keys

Got it. Then how do I dispatch values to individual keys? Can you share an example?

you just generate the whole map at once

Aha will try that. So local dependency is propagated to global in this case.

simplest example: always return the same map

👍 1

user=> (mg/generate [:map {:gen/return {:a 1 :b 2 :c 3}} [:a :int] [:b :int] [:c :int]])
{:a 1, :b 2, :c 3}

here's a real example:

user=> (mg/generate [:map {:gen/gen (gen/let [x gen/nat] (gen/return {:a x :b (inc x) :c (dec x)}))} [:a :int] [:b :int] [:c :int]])
{:a 9, :b 10, :c 8}

(had to take a refresher in test.check)

Yea got it. Thanks!

to tweak a little, I could return nil (or whatever) for the second argument for gen/fmap, and use the first argument to return the data I want. In this case new data is generated whenever mg/generate is triggered.