This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-02-14
Channels
- # aws (1)
- # bangalore-clj (1)
- # beginners (48)
- # boot (65)
- # braveandtrue (1)
- # cider (1)
- # clara (15)
- # cljs-dev (7)
- # clojure (179)
- # clojure-austin (1)
- # clojure-denmark (2)
- # clojure-greece (68)
- # clojure-italy (7)
- # clojure-russia (41)
- # clojure-serbia (9)
- # clojure-spec (44)
- # clojure-uk (27)
- # clojured (15)
- # clojureremote (20)
- # clojurescript (70)
- # community-development (2)
- # core-async (10)
- # cursive (14)
- # datomic (36)
- # defnpodcast (3)
- # emacs (13)
- # events (13)
- # hoplon (33)
- # immutant (18)
- # instaparse (2)
- # jobs (29)
- # jobs-discuss (71)
- # klipse (38)
- # lein-figwheel (4)
- # leiningen (1)
- # mount (34)
- # off-topic (36)
- # om (3)
- # onyx (51)
- # pedestal (5)
- # perun (8)
- # proton (2)
- # rdf (8)
- # re-frame (33)
- # reagent (24)
- # remote-jobs (1)
- # rum (6)
- # spacemacs (2)
- # specter (14)
- # sql (5)
- # testing (6)
- # untangled (1)
- # vim (10)
- # yada (3)
@shader that first error was fixed in 0.13.2, as for second issue would need to see the code producing the error to help
@nathanmarz, I'm finding with-fresh-collected
to be incredibly useful.
(s/def ::or-spec-path-args
(s/cat :spec qualified-keyword?
:branches (s/+ (s/alt :branch (s/cat :key simple-keyword? :body any?)
:invalid (s/cat :key #{:spec/invalid} :body any?)))))
(defmacro or-spec-path
"Navigates to one of several subpaths depending on which branch of a
`clojure.spec/or` the structure conforms to."
[& args]
(let [{:keys [spec branches] :as conformed} (s/conform ::or-spec-path-args args)
spec-obj (s/get-spec spec)
invalid (or (select-first (fn [[tag _]] (= :invalid tag))
branches)
`(fn [val#] (throw (ex-info (s/explain-str ~spec val#)
(s/explain-data ~spec val#)))))]
(if-not spec-obj
(throw (ex-info (str "Spec not found: " spec)
{:spec spec
:conformed conformed}))
`(with-fresh-collected
(collect-one (view (partial s/conform ~spec)))
(cond-path
(collected? [conformed#]
(= ::s/invalid conformed#))
~invalid
~@(mapcat (fn [[_ {:keys [key body]}]]
`[(collected? [[tag# ~'_]]
(= tag# ~key))
~body])
branches))))))
(s/def ::case-path-args
(s/cat :path any?
:branches (s/+ (s/cat :value any? :body any?))
:default (s/? any?)))
(defmacro case-path
"Navigates to one of several subpaths depending on the value selected by a the
provided path."
[& args]
(let [{:keys [path branches default] :as conformed} (s/conform ::case-path-args args)]
`(with-fresh-collected
(collect-one ~path)
(cond-path
~@(mapcat (fn [{:keys [value body]}]
`[(collected? [value#]
(= value# ~value))
~body])
branches)
~@(when default
`[(collected? [value#]
true)
~default])))))
@zane cool, you should be able to do those as dynamic navs though
Hmm. Could I do the spec one as a dynamic nav? I want to have compile-time error reporting for that one.
I haven't dug into spec yet, so I don't understand every detail of your code. But if you did it as a dynamic nav it would throw the error the first time that callsite is run (when Specter's inline compiler expands dynamic navs).
Another approach you could take is have a macro that does your validation and expands to a dynamic nav invocation which does the rest of the work.
opened a thread on the mailing list about whether Specter should be part of Clojure core or not https://groups.google.com/forum/#!topic/clojure/qN1UPMVQmaM