This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-20
Channels
- # 100-days-of-code (2)
- # aleph (53)
- # architecture (2)
- # aws (3)
- # beginners (230)
- # boot (15)
- # calva (3)
- # cider (19)
- # cljs-dev (1)
- # clojure (139)
- # clojure-conj (3)
- # clojure-italy (47)
- # clojure-nl (19)
- # clojure-spec (26)
- # clojure-uk (98)
- # clojurescript (152)
- # clojutre (4)
- # core-async (22)
- # cursive (5)
- # datomic (48)
- # emacs (11)
- # events (1)
- # figwheel-main (219)
- # fulcro (15)
- # instaparse (3)
- # jobs (4)
- # jobs-rus (1)
- # leiningen (30)
- # luminus (8)
- # off-topic (67)
- # onyx (5)
- # pedestal (16)
- # re-frame (1)
- # reagent (4)
- # reitit (31)
- # ring (8)
- # ring-swagger (3)
- # shadow-cljs (115)
- # specter (4)
- # videos (1)
- # vim (20)
- # yada (15)
Is there a catenation which doesn't care about order?
I have specs ::a
, ::b
, ::c
and ::d
.
I want a catenation in which ::a
and ::b
are required, ::c
and ::d
are optional and order doesn't matter. Is this possible with spec?
Does what you said
s/keys* works on sequential collections
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (s/def ::a int?)
:user/a
user=> (s/def ::b string?)
:user/b
user=> (s/def ::c keyword?)
:user/c
user=> (s/def ::d symbol?)
:user/d
user=> (s/def ::s (s/keys* :req [::a ::b] :opt [::c ::d]))
:user/s
user=> (s/conform ::s [::b "abc" ::c :wow ::a 100])
#:user{:b "abc", :c :wow, :a 100}
user=> (pprint (take 5 (s/exercise ::s)))
([(:user/a 0 :user/b "" :user/d q :user/c :T)
#:user{:a 0, :b "", :d q, :c :T}]
[(:user/a -1 :user/b "" :user/d !D/- :user/c :oh)
#:user{:a -1, :b "", :d !D/-, :c :oh}]
[(:user/a 1 :user/b "kK") #:user{:a 1, :b "kK"}]
[(:user/a -4 :user/b "3" :user/d Jw/R5 :user/c :?jH)
#:user{:a -4, :b "3", :d Jw/R5, :c :?jH}]
[(:user/a 0 :user/b "Y6" :user/d NS.+_.H/-)
#:user{:a 0, :b "Y6", :d NS.+_.H/-}])
there is a way to do exactly what keys*
does but using quoted symbols instead of keywords?
ex:
(s/conform ::foo [:source1 '-> :target1 'guard #() 'action #()])
Where the 'guard and the 'action maybe defined or not but the :source1 '-> :target1
should be required.keys* is capturing the common Clojure idiom of kwargs passed to a function (but those are always keywords)
I would probably use regex for that
(s/cat :s keyword? :_ #{'->} :t keyword? (s/* (s/alt :guard-pair (s/cat :_ #{'guard} :g any?) :action-pair (s/cat :_ #{'action} :a any?))))
or could be simpler if you want to spec less of the options (s/cat :s keyword? :_ #{'->} :t keyword? (s/* (s/cat :op symbol? :val any?)))
@U064X3EF3 thank you sir! I should have perused the clojure.spec.alpha
docs.
You could probably do the s/or of all the possible orders, but that would be pretty tedious and error prone.
Why do you want a catenation if the order doesn't matter? Are these args to a function?
Trying to implement serialization and deserialization of a protocol using conform
and unform
.
To see just how much of it can be pushed into spec? This is the last step.
Actual use case contains ~20 specs, so s/or
ing 20 factorial orders is out of the picture.
I think I keep asking roughly the same question in different contexts but hoping someone can help me understand the best way to approach this: I need to programmatically create a spec based on external data (specifically, a GraphQL schema/query). Is there any good examples out there of how to approach this?