This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-08-19
Channels
- # announcements (4)
- # asami (1)
- # babashka (48)
- # beginners (84)
- # bristol-clojurians (1)
- # calva (15)
- # chlorine-clover (11)
- # cider (37)
- # clj-kondo (17)
- # clojure (72)
- # clojure-europe (13)
- # clojure-italy (43)
- # clojure-nl (6)
- # clojure-spec (8)
- # clojure-uk (19)
- # clojuredesign-podcast (7)
- # clojurescript (132)
- # code-reviews (7)
- # conjure (3)
- # cursive (24)
- # datascript (10)
- # datomic (61)
- # docker (4)
- # duct (24)
- # emacs (2)
- # figwheel-main (8)
- # fulcro (43)
- # graalvm (5)
- # juxt (1)
- # keechma (14)
- # malli (2)
- # off-topic (120)
- # re-frame (111)
- # reagent (6)
- # reitit (13)
- # shadow-cljs (118)
- # spacemacs (3)
- # tools-deps (32)
- # uncomplicate (5)
- # xtdb (6)
Hi, Would appreciate some help 🙂 What am I doing wrong? I have a spec for an empty map: `
(s/def ::empty_map (s/and empty? map?))
and then I build:
`
(s/def ::name string?)
(s/def ::someone1 string?)
(s/def ::someone2 string?)
(s/def ::someone_big (s/or
::empty_map
(s/keys :req-un [::someone1 ::someone2])))
(s/def ::final (s/keys :req-un [::name ::someone_big]))
The idea here that I would be able to pass:
{:name "abc" :someone_big {}}
And it wold pass, since it is an empty map.
But what I get is an error on the required params:
(s/explain ::final {:name "abc" :someone_big {}})
{} - failed: (contains? % :someone1) in: [:someone_big] at: [:someone_big :<NS>empty_map] spec: :<NS>/someone_big
{} - failed: (contains? % :someone2) in: [:someone_big] at: [:someone_big :<NS>/empty_map] spec: :<NS>/someone_big
Any help would be appreciated 🙂@bhaim123 You need to label each branch of the s/or
e.g.
(s/def ::someone_big (s/or :empty-map ::empty_map
:someone (s/keys :req-un [::someone1 ::someone2])))
user=> (s/conform ::final {:name "abc" :someone_big {}})
{:name "abc", :someone_big [:empty-map {}]}
Thanks, but I don’t want to send the keyword empty map, the someone_big should be either an empty map. or a map of 2 keys
I’m not sure I follow. The spec does capture that it’s either an empty map or a map of two keys. You’re not “sending” any keywords, you’re labelling alternatives. Both (s/conform ::final :empty-map)
and (s/conform ::final :someone)
are invalid for this spec.
The original ::someone_big
spec you posted was a s/or
with 1 branch: it could only be a map with two keys and it was labelled ::empty_map
.
If you reversed the order it might be clearer why it’s wrong:
(s/def ::someone_big (s/or
(s/keys :req-un [::someone1 ::someone2])
::empty_map))
Unexpected error (AssertionError) macroexpanding s/or at (REPL:1:22).
Assert failed: spec/or expects k1 p1 k2 p2..., where ks are keywords
(c/and (even? (count key-pred-forms)) (every? keyword? keys))
as an aside, (s/def ::empty_map (s/and map? empty?))
would be better than what you have as it should gen when the other would not