Fork me on GitHub
#malli
<
2024-01-23
>
tony.kay02:01:35

Hey there. I’m relatively new to using malli, and I’ve got a regular case that I was doing with spec that I cannot figure out with the sequential schemas that malli supports. I want to validate like s/every?, but my value could be a lazy seq, list, set, vector, or even map…basically anything that you can seq. I’ve tried all of the built-in stuff I’ve found, and have resorted to making my own:

(m/-collection-schema {:type :every, :pred coll?})
I don’t see that anywhere in Malli. Should it be there? Is there something I’ve missed that does the same thing?

ikitommi05:01:21

No such thing at the moment. So, would coll? match all of those? if so, maybe a new`:collection` schema?

ikitommi05:01:58

[:collection :int]
[:collection {:min 1, :max 10} :any]
[:collection {:distinct true, :min 1} :string]

tony.kay17:01:15

So I’m porting over code that uses s/every and s/coll-of, and both of those don’t care what kind of collection it is, though they have an option to help with generators (:into). every is NOT exhaustive (for performance) and coll-of is. I like them both, but having something close to either would be great. The -collection-schema I proposed above is what I installed in my registry, and it has covered the cases I’ve hit so far.

ikitommi18:01:16

ok. good to hear you are happy with that. I’m open to adding :collection that to malli, but it would also needs these: • error messages • generator • json-schema mapping • transforming mappings

tony.kay18:01:11

ah good point. I’m not deep enough into Malli yet to have used any of that except error messages 😄

tony.kay02:01:15

otherwise I’m having to write things like [:or [:set :int] [:sequential :int]]

escherize03:01:30

I have a pretty flexible, recursive schema https://github.com/escherize/huff/blob/master/src/huff2/core.clj#L29-L58. Are there any tricks for getting better error messages?

jeroenvandijk05:01:57

I think instead of :orn you could use : multi . This will show an error for one branch only, where as :orn will explain in the context of all branches, because malli cannot now what branch it was supposed to dispatch on.

ikitommi05:01:24

the regex errors are really bad atm and should be improved (just need to figure out how, ideas welcome). here’s my test on “schemas of schemas” with :enum syntax. Simplest possible case and the error is 🙈

ikitommi05:01:24

the regex errors are really bad atm and should be improved (just need to figure out how, ideas welcome). here’s my test on “schemas of schemas” with :enum syntax. Simplest possible case and the error is 🙈

Marius14:01:09

Hey there! Is there a way with Malli coercion to remove optional keys if their value is nil instead of e.g. an integer?

hifumi12309:01:18

Nothing out-of-the-box in Malli, but using a custom decoder for your map schema, you should be able to walk map entries and ignore those with nil value.

Marius09:01:50

Okay, thanks! I haven’t looked in to custom decoders, yet - might be worth a try

hifumi12309:01:53

It’s a bit tricky to get right at first, but Malli does have some built-in functions for e.g. stripping extra keys. That may help guide you

andersmurphy14:02:38

Something like this should work:

(def strip-nil-transformer
  (let [strip-nil
        {:compile
         (fn [schema _]
           (let [default-schema (m/default-schema schema)]
             {:enter
              (fn [x]
                (if (and (map? x) (not default-schema))
                  (reduce-kv
                    (fn [acc k v]
                      (if (nil? v) (dissoc acc k) acc))
                    x x)
                  x))}))}]
    (mt/transformer
      {:decoders {:map strip-nil}})))

Marius10:03:36

I’ll try it out, thank you!

allentiak18:01:00

Hi, I'm moving from clojure.spec to malli. I'm having it hard to instrument a function's output. In this case, I want to make sure that the output is larger or equal than the input. In spec, I would use

(s/fdef area-of-square
  :args (s/cat :len nat-int?)
  :ret nat-int?
  :fn #(>= (:ret %)
           (:len %)))
In Malli, I'm using defn's metadata syntax:
(defn area-of-square-with-schema
  [len]
  {:malli/schema [:=> [:cat nat-int?] [:and
                                        nat-int?
                                        (>= area length)]]}
  (* len len))
I get an invalid schema exception. How would you suggest I go about this? Again, I want to make sure that the output ("area") is larger or equal than the input ("length").

Noah Bogart18:01:35

[:and nat-int? [:fn (fn [{:keys [area length]}] (>= area length))]] should be right

ikitommi19:01:24

, but - there is no way to correlate inputs & outputs currently like :fn is for spec. Should be easy to add thou.

allentiak19:01:42

@UEENNMX0T Thanks for your answer, but what I'm trying to find here is a way for the output to refer not only to the input, but also to its own value. Your suggestion assumes I have two input params (`area` and lenght); however, I only have one: length. (`area` is the way in which I refer to the output value). I tried the following code, with :catn (for named params). But I get the same error:

[:=> [:catn [:len nat-int?]]
     [:catn [:area
              [:and
               nat-int?
               [:fn (fn [{:keys [area len]}]
                                    (>= area len))]]]]]}

👍 1
ikitommi19:01:46

there might be an issue for this, if not, please write one?

allentiak19:01:47

Thanks for your answer, @U055NJ5CC! I found the corresponding issue: https://github.com/metosin/malli/issues/936

👍 1
tomc23:01:03

Hi all, a couple Malli questions: • would the maintainers accept a PR that adds a table of contents and perhaps slightly reorganizes the readme? • Is there a built-in schema for anything "listy"? That is: lists, seqs, vectors, and sets. (side note, is there a term for these things that excludes maps? Basically, a collection of values, but not keyed values) • If there's no built-in for that, is the best approach to use something like [:or [:set Schema] [:sequential Schema]] ?

ikitommi07:01:47

• doesn’t github has auto-toc nowadays? see the pic. • improving README is most welcome, big re-org - maybe, if it clearly makes things better, would need to see the changes first • the last one, I think this was just discussed yesterday, see https://clojurians.slack.com/archives/CLDK6MFMK/p1705977455955919

tomc15:01:12

Thanks, this answers my questions. I guess I never noticed the TOC button on github 😄