Fork me on GitHub
#malli
<
2023-09-06
>
Yevgeni Tsodikov10:09:10

Hi, Is there a built-in schema for Java list/collection validation? Something like [:vector :map], but for java.util.Collection?

Yevgeni Tsodikov10:09:20

I know I can create my own type with:

(m/-collection-schema {:type :java-collection, :pred #(instance? java.util.Collection %)})
But looking for alternatives

ikitommi13:09:13

no, there is nothing built-in. Same applies for concrete classes like Long, Integer. I you end up with a set of new schemas for java types, please share here.

ikitommi13:09:27

I have a draft for effective types of schemas, so you derive generators, providers, transformers from effective type, :java-collection is kinda :vector. without this, you need to mount each new type separately.

Chip11:09:36

That’s cool

opqdonut12:09:24

thanks 🙂

Samuel Ludwig14:09:23

noob "what am I doing wrong?" style question regarding :fn constraints and generation (contents in thread to not pollute channel):

2
Samuel Ludwig14:09:29

I'm playing around, and trying to create a spec of what an entry in some kind of version log might look like, with a :fields-changed (set), :before (map), and :after (map) key. I want to enforce a constraint that the keywords in the :fields-changed set are a subset of the keys in the :before and :after maps. My spec is as follows:

(mg/generate
 [:and
  {:gen/fmap (fn [{:keys [fields-changed]}]
               {:fields-changed fields-changed
                :after (zipmap fields-changed (repeatedly #(rand-int 100)))
                :before (zipmap fields-changed (repeatedly #(rand-int 100)))})}
  [:map
   [:fields-changed [:set keyword?]]
   [:before map?]
   [:after map?]]
  [:fn (fn [{:keys [fields-changed before after] :as m}]
         (tap> m)
         (and (set/subset? fields-changed (-> before keys set))
              (set/subset? fields-changed (-> after keys set))))]])
I suspect my :gen/fmap function is incorrect, and to tell the truth I'm not completely comfortable with generator stuff in general. I'm currently getting couldn't satisfy such-that errors every other generate call or so (it works when there's no keys generated)

Stig Brautaset14:09:50

TIL about :gen/fmap. We use that quite a lot in Spec at work, and me thinking it was missing from malli was one reason why I didn't think it would work for us -- so thank you 🙂

🙌 2
Stig Brautaset14:09:23

I can't tell what's wrong though...

Samuel Ludwig15:09:26

yea, im not sure, zipmap should be kosher to use with sets, so I don't think its that

Samuel Ludwig15:09:42

my suspicion is that it might be checking the :fn relation before the generation maybe? but that would be counter to my purpose of providing a custom generator (to side-step hard-to-generate things)

Samuel Ludwig15:09:20

that tap> reveals maps that are clearly all randomly generated, and not a result of the fmap call; for example

{:fields-changed
  #{:A./*?3+bY-L
    :mn/+--+!**
    :!*m/!e95:T
    :sL:_/r
   ...
    :_r3?/MKsW
    :_8/S?-0T6},
  :before
  {-34238756986650630276294N 4,
   true \;,
   #uuid "485d16b8-7d0c-4f91-9d47-285b2f7921a2" :JQoO-:W,
   ...
   "Vb*$&Qk7T" "I;qPI)"},
  :after {true :Hg, 6 2}}

Samuel Ludwig17:09:09

does the generator only 'attach' to the schema if its a :gen/gen "property" (think I'm using the correct term there)?

ikitommi17:09:59

@U0482NW9KL1 you should move the :gen/fmap to the :map schema instead, this way, it's done before the :fn

Samuel Ludwig17:09:58

ahhh, so for reference, like so:

(mg/generate
 [:and
  [:map
   {:gen/fmap 
    (fn [{:keys [fields-changed]}]
     {:fields-changed fields-changed
      :after (zipmap fields-changed (repeatedly #(rand-int 100)))
      :before (zipmap fields-changed (repeatedly #(rand-int 100)))})}
   [:fields-changed [:set keyword?]]
   [:before map?]
   [:after map?]]
  [:fn (fn [{:keys [fields-changed before after] :as m}]
         (tap> m)
         (and (set/subset? fields-changed (-> before keys set))
              (set/subset? fields-changed (-> after keys set))))]])

ikitommi17:09:40

(there could be an :gen/ignore or similar to omit checking the extra constraints witj :and, but there is no such thing ATM)

ikitommi17:09:57

does that work?

Samuel Ludwig17:09:25

it does!, interesting, didn't know the order had mattered like that 😅

👍 2
ikitommi17:09:04

:and generates on first child and validates on whole schema, :gen/fmap there works on the value returned, e.g. “too late”