This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-05-14
Channels
- # beginners (74)
- # boot (1)
- # cider (6)
- # clj-kondo (8)
- # cljs-dev (30)
- # clojure (195)
- # clojure-ecuador (1)
- # clojure-europe (2)
- # clojure-italy (51)
- # clojure-nl (47)
- # clojure-spec (9)
- # clojure-sweden (27)
- # clojure-uk (63)
- # clojurescript (84)
- # cursive (41)
- # datascript (17)
- # datomic (16)
- # docker (1)
- # emacs (10)
- # events (2)
- # graalvm (2)
- # graphql (37)
- # juxt (2)
- # nrepl (20)
- # nyc (2)
- # off-topic (26)
- # onyx (3)
- # pedestal (4)
- # perun (19)
- # planck (1)
- # reagent (9)
- # reitit (4)
- # shadow-cljs (208)
- # spacemacs (6)
- # tools-deps (4)
Any ideas on how to spec this?
Essentially I have a heterogenous map; if a key in that map is a vector of length N then I’d like to spec that the value of that key in the map is a sequence of tuples also of length N.
If a key in the map is not a vector, than its key can be any?
When defining your fspec's :fn
, what's the intended way to interact with args that are s/or
specs? For example:
{:fn #(-> % :args :arg-name)
for such an arg yields a vector that starts with the keyword for the s/or
variant. Here's how I could approach it:
(s/def ::example (s/or :map map?
:num int?))
(defn myfn [int-arg example-arg])
(s/fdef myfn
:args (s/cat :int-arg int?
:example-arg ::example)
:fn #(-> % :args :example-arg
(as-> [path value]
(or (not= path :map)
(contains? value (-> % :args :int-arg))))))
(myfn 1 {2 :a 3 :b}) ;; => fails
Here, :fn
ensures that the first arg is a key in the second arg if the second arg is a map. Is this how I should be writing these :fn
s, or is there a better way?if it's just an inter-arg dependency, you can s/& that predicate onto the args spec
rather than using :fn, which has access to both args and ret
alternately, you could encode the args with an s/alt for your two alternatives
(s/alt :not-map (s/cat :int-arg int? :example-arg #(not (map? %)))
:map (s/& (s/cat :int-arg int? :example-arg map?) #(contains? %2 %1)))
something like that for the args if I understood all that right
and as an aside, when something is hard to spec like this with options, it's often a good sign that your function is doing two things and having 2 functions might be better