This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-03
Channels
- # announcements (5)
- # babashka (7)
- # beginners (119)
- # biff (4)
- # cider (7)
- # clj-kondo (26)
- # cljfx (3)
- # cljs-dev (2)
- # clojure (28)
- # clojure-austin (18)
- # clojure-europe (9)
- # clojure-france (6)
- # clojure-norway (4)
- # clojure-uk (3)
- # clojurescript (6)
- # community-development (1)
- # core-async (4)
- # cursive (9)
- # data-science (12)
- # datomic (13)
- # duct (18)
- # emacs (15)
- # etaoin (5)
- # events (13)
- # honeysql (46)
- # hyperfiddle (9)
- # jackdaw (5)
- # jobs (13)
- # keechma (4)
- # lsp (37)
- # malli (32)
- # nbb (14)
- # off-topic (10)
- # other-languages (2)
- # polylith (4)
- # programming-beginners (3)
- # reagent (27)
- # reitit (1)
- # shadow-cljs (32)
- # sql (11)
- # tools-build (5)
- # tools-deps (3)
- # vim (14)
- # xtdb (11)
Hey y'all, I'm wondering if it's possible in Malli to create a spec for a map with these qualifications:
• There are some specific keyword keys that are required (this is simple in Malli)
• There can also be an arbitrary amount of keys that are vectors, but they all must be vectors of keywords and their values must be maps. (not straightforward)
• Besides the two possibilities above, the map is closed (ex no string keys for example, also not straightforward)
The last two things are the weird requirements. Seems like :map
can't really support this. I might need to use [:and [:map ... ] [:fn ...]
but even then it might be awkward to satisfy #3.
[:and
[:fn (fn [m]
(->>
(dissoc m :specified :optional :required)
(m/validate (m/schema [:map-of keyword? string?]))))]
[:map
[:required [:enum :a :b]]
[:optional {:optional true} [:enum :a :b]]
[:specified :int]]]
make a function that outputs something like this@U0LAJQLQ1 thank you for the help! I'm going to look at this later.
just be aware that i didn't provide a general function, you need to create one that respects the keys in your malli map schema.
A little update, I realized that clojure.spec can solve this problem with actually great error messages so I might rewrite in spec. Might write a blog post about it later too.
What's the best way to express in malli "a map must contain at least one of a set of kv"?
is that :or
or :multi
?
I also think this requires some awareness of implementation details to get coercion right, because when dealing with two keys, you'll want to try to coerce both, i.e. [:or [:merge Ma Mb] Ma Mb]]
you could also do a function schema for this, make the various keys optional and then perform the check in the :fn
any particular reason? seems appropriate for this kind of work
They're completely opaque, not well defined, not serializable, hard up to impossible to generate
The semantics of "at least one of this group" are clear, don't need a function. It can (should) be another schema type
That makes sense to me. I wonder how hard it is to write a new schema type like this
Is it? Naively, I would expect it to be an or
:
(fn [obj]
(or (contains? obj :a)
(contains? obj :b)
(contains? obj :c)))
or something similar. is there more to it?Maybe I'm misunderstanding the actual problem
because there's a combinatoric explosion, you need for two keys:
[:or [:map [:k1 S1] [:k2 S2]] [:map [:k1 S1]] [:map [:k2 S2]]]
"At least one of a set" means as long as one exists, it doesn't matter if others exist, so you can just check each one
could compile a list of the ones that do exist and then merge them after the fact too
hah I won't be nerd sniped! but yes, if you don't want to directly implement a bunch of stuff, I think I can see the issue more clearly