This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-12-01
Channels
- # adventofcode (66)
- # announcements (12)
- # aws (8)
- # babashka (28)
- # beginners (160)
- # cider (28)
- # clara (22)
- # clj-kondo (5)
- # cljdoc (40)
- # clojure (129)
- # clojure-australia (2)
- # clojure-europe (24)
- # clojure-gamedev (19)
- # clojure-nl (5)
- # clojure-norway (15)
- # clojure-sanfrancisco (25)
- # clojure-seattle (2)
- # clojure-spec (13)
- # clojure-uk (29)
- # clojurescript (14)
- # cryogen (5)
- # cursive (7)
- # data-science (1)
- # datascript (5)
- # datomic (8)
- # deps-new (5)
- # emacs (19)
- # events (8)
- # fulcro (32)
- # graalvm (7)
- # helix (9)
- # kaocha (3)
- # lambdaisland (1)
- # london-clojurians (4)
- # malli (5)
- # meander (32)
- # off-topic (143)
- # pathom (4)
- # portal (32)
- # re-frame (7)
- # reagent (33)
- # reitit (2)
- # shadow-cljs (5)
- # spacemacs (4)
- # tools-deps (30)
- # vim (1)
What’s the best to way to list the keys that a map is missing? E.g. with a problem like this for a specced map, what do you guys do to collect those key-name
s? I’m looking at using spec to validate data in a web app so ultimately I’d like to translate the missing keys into a message like “<key-name> is required” but I’m not sure what’s the best way to get a hold of the names of the missing keys.
{:path [],
:pred (clojure.core/fn [%] (clojure.core/contains? % :key-name)),
:val
{},
:via [,,,],
:in []}
I was looking through expound to try to see how they do it.. it looks like the core of it is https://github.com/bhb/expound/blob/1c0d78570be3865eab8e69c1b568c4e7acee5bd8/src/expound/printer.cljc#L187-L194, where form
is a :pred
https://github.com/bhb/expound/blob/1c0d78570be3865eab8e69c1b568c4e7acee5bd8/src/expound/alpha.cljc#L317.. but I don’t understand how that :expound.spec/contains-key-pred
works..
I don’t see how it returns the name of the failed key.. when I try something similar it just returns ::s/invalid
, which seems like what I would expect.
@UPGS9BS0L Expound is just parsing the s-expression of the pred. The trick is that expound will take the pred e.g. something like
(clojure.core/fn [%] (clojure.core/contains? % :expound.printer/foo))
And then it will throw away the clojure.core/fn [%]
part with the (nth form 2)
on line 188
Here’s a little script to show each step. It’s just an example to show how Expound figures out each part of the :pred
(let [first-problem (first (::s/problems (s/explain-data ::some-spec {})))]
{
:pred (:pred first-problem)
:part-of-pred (nth (:pred first-problem) 2)
:match (s/conform :expound.spec/contains-key-pred (nth (:pred first-problem) 2))
}
)
;; This returns:
#_ {:pred (clojure.core/fn [%] (clojure.core/contains? % :expound.printer/foo)),
:part-of-pred (clojure.core/contains? % :expound.printer/foo),
:match [:simple {:contains clojure.core/contains?, :arg %, :kw :expound.printer/foo}]}
ah cool, yeah that does make sense. Thank you! So is that how you’d recommend going about getting a hold of those keys? Is there a simpler way to just get spec to tell me which req
keys are missing?
@UPGS9BS0L Unfortunately, as of spec1, that’s the way I know of to get the missing keys. Things may change in spec2, but I don’t know of any specific plans for this.
It’d be really nice if spec2 included both the missing key and the fully-qualified key in the case of keys included via :req-un
.
(right now if you use :req-un
, sometimes Expound will warn <can't find spec for unqualified spec identifier>
because it doesn’t know what spec you meant by the kw :foo
)
@UPGS9BS0L This is apparently how Phrase works as well https://cljdoc.org/d/phrase/phrase/0.3-alpha4/doc/examples#required-keys
This is really helpful, then. Thanks for all the info!