This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-08
Channels
- # aleph (1)
- # architecture (4)
- # aws (5)
- # beginners (105)
- # boot (1)
- # boot-dev (72)
- # cider (5)
- # clara (15)
- # cljs-dev (51)
- # cljsrn (5)
- # clojure (155)
- # clojure-austin (3)
- # clojure-dusseldorf (2)
- # clojure-finland (1)
- # clojure-greece (37)
- # clojure-italy (17)
- # clojure-nl (1)
- # clojure-russia (6)
- # clojure-spec (23)
- # clojure-uk (6)
- # clojurescript (7)
- # community-development (1)
- # css (10)
- # cursive (15)
- # datomic (45)
- # defnpodcast (1)
- # duct (97)
- # emacs (5)
- # fulcro (46)
- # hoplon (8)
- # instaparse (25)
- # keechma (11)
- # leiningen (16)
- # off-topic (2)
- # onyx (9)
- # planck (2)
- # re-frame (5)
- # reagent (3)
- # reitit (2)
- # ring (6)
- # shadow-cljs (35)
- # spacemacs (9)
- # specter (9)
- # sql (18)
- # uncomplicate (4)
I'm trying to write a util that prints out a more friendly error message based on the data returned from s/explain-data
. I'm noticing that :in
contains misleading data for certain cases:
user=> (s/explain-data (s/map-of integer? integer?) {345 "a"})
{:clojure.spec.alpha/problems ({:in [345 1],
:path [1],
:pred clojure.core/integer?,
:val "a",
:via []}),
:clojure.spec.alpha/spec #<[email protected]>,
:clojure.spec.alpha/value {345 "a"}}
user=> (s/explain-data (s/coll-of integer? :kind set?) #{1 2 "a"})
{:clojure.spec.alpha/problems ({:in [1],
:path [],
:pred integer?,
:val "a",
:via []}),
:clojure.spec.alpha/spec #<clojure.spec.alpha$every_impl$r[email protected]>,
:clojure.spec.alpha/value #{1 2 "a"}}
So for a map-of
, it is giving me the key as well as 1
(to indicate the val of the map pair), and for a set, it is giving me an index into some arbitrary ordered version of that set. Neither of these would work if I tried to get-in
on those paths.
If these values were somehow prefaced with an indicator of what special case triggered them, I could work with that, but the fact that the data may or may not be misleading with no additional context makes the overall data unhelpful for writing a universal tool. Is that a bug? Or is there another way of introspecting the failed specs that I'm missing?on the first case, this is a side effect of treating maps as a sequence of tuples. there is at least one ticket about this particular one with a pending patch.
for the set case, I don’t think anything is logged but a ticket for that would be fine
Thanks, I'll try to find time to write up a ticket. I'll definitely check out the other ticket you mentioned for map-of
, since I'm curious what the proposed solution was, so I know what the expected behavior should be for sets.
I ended up writing a lot of code to disambiguate these cases in Expound. https://github.com/bhb/expound/blob/master/src/expound/paths.cljc . The ticket for map-of is https://dev.clojure.org/jira/browse/CLJ-2192 .
IIRC, https://github.com/athos/Pinpointer takes a different approach to the problem: it analyzed the specs directly to help understand the explain-data
(I could be mis-stating something here, @U0508956F please correct me if I’m wrong 🙂 )
@U08EKSQMS thanks! do you have any specific thoughts on the set issue as well? are you also handling that specially from expound?
I haven’t traced the execution too closely, but I suspect that the set case is handled by this code https://github.com/bhb/expound/blob/master/src/expound/paths.cljc#L134-L135
This could have bugs though. It took awhile to figure out an approach that would work for most :in
paths that I could find.
Re: sets, I would vote for any JIRA ticket that makes :in
paths non-ambiguous, because I think this is one of the biggest hurdles with building pretty-printers for spec. If you make an issue for the set case, send me the link 😄
Thanks @U08EKSQMS, I’ve been meaning to take a closer look at Expound actually
@aengelberg I’d like to see that too if you find it.
- zero?
throws on strings, keywords, etc.
- just (complement neg-int?) accepts everything but neg ints: strings, maps, etc.
What about nat-int?
Given the following data: {:a {:name "a"} :b {:name "b"} :c {:name "not-c"}}
, how could I construct a spec to say "the key to a value-map must be the keywordized name within the value-map"? This spec would complain that (keyword "not-c")
does not match :c
You can use any arbitrary predicate like #(= (keys %) (->> % vals (map :name) (map keyword)))
to check validity
but it’s not going to give you that specific error