This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-28
Channels
- # announcements (6)
- # aws (8)
- # bangalore-clj (1)
- # beginners (249)
- # calva (27)
- # cider (5)
- # clara (8)
- # clj-kondo (11)
- # cljs-dev (14)
- # cljsrn (21)
- # clojars (1)
- # clojure (206)
- # clojure-europe (3)
- # clojure-greece (2)
- # clojure-italy (39)
- # clojure-nl (19)
- # clojure-spec (50)
- # clojure-uk (19)
- # clojurescript (31)
- # clojurex (24)
- # community-development (10)
- # core-async (32)
- # core-typed (4)
- # cursive (8)
- # data-science (15)
- # datomic (42)
- # figwheel (1)
- # fulcro (18)
- # graalvm (6)
- # joker (1)
- # kaocha (1)
- # nyc (1)
- # off-topic (1)
- # reagent (5)
- # reitit (2)
- # remote-jobs (2)
- # shadow-cljs (3)
- # spacemacs (2)
- # tools-deps (65)
- # xtdb (3)
(reposted from #clojure) I've got a problem I think spec would be perfect for, but I'm a total spec noob and have no idea how to spec it. I'm using pseudo set notation to describe the problem (read "m E S" as "m is a member of set S"). --- Given: There's a set of types, T, There's a set of attributes, A, There's a set of specs S There's a map such that every attribute has a corresponding spec from S. What is the spec for 2-tuples where: - The first element R1 is a vector of where every element e E T. - The second element R2 is a set of tuples in the form [e a v], where e E {1..length of R1}, a E A, and the value of v conforms to the spec corresponding to a. Any help is appreciated!
so the first spec seems easy enough:
(s/def ::T #{:t1 :t2 ,,,})
You could map A and S manually by doing:
(s/def ::attribute-that-is-a-number number?
,,,
If you need to make the set of A to be concrete you'd probably want to look up the registry
Then the final spec for your 2-tuple probably involves quite a hairy predicate (remember that all specs are 1-arg preds)
This could then check that every first-element of the R2 is is a member of the set of ints from 1 up to (count R1)
Then a spec that looks up value of a in R2 and does (s/valid? a v)
Lol, why did I have to pick this as my first venture into specs 😛. Let’s try making it more concrete.
(s/def ::T #{:t1 :t2})
(s/def ::height number?)
(s/def ::name string?)
(s/def ::A #{::height ::name})
(s/def ::Goal (s/cat :R1 int? :R2 ???))
… That’s all I got so far! Can I get a hint on the rest of the syntax?
Maybe
(s/def ::Goal (s/cat :R1 int? :R2 (s/* (s/cat :e (set (range (count R1))) :a ??? v: ???)))
if you don't think about ::Goal
as a spec but more a function that takes the whole 2-tuple what would that function look like
Yeah, you’re right, :R1 is more like (s/col-of ?int)
.
Yeah, technically, t
There’s more to it though, right @UCF779XFS? I need some predicate function that @U0HJD63RN was alluding to.
so you’d have something like:
(defn valid-val?
[[idx a v]]
(s/valid? a v))
(s/and (s/cat _ _ _ _ _ _)
valid-val?)
something like that/ where the empty cat is whatever you’re using for the three values in the R2 element
Ok.. this is starting to come together!
well from the description of the specification - R2's permissible values for e
depends on R1
Yeah, that's right.
(let [[r1 r2] tup
allowed-e? (->> r1 count inc (range 1) (into #{}))]
(->> r2 (map first) (every? allowed-e?))
something like this maybeI’ll give that a shot later, thanks!
so I guess you could split the spec for your tuple into three checks: That R1 is valid all e are valid wrt R1 all v conform to their corresponding a
Yes! That sounds very doable
I was hoping to get generators for free, but even besides this, there are other constraints that between entities of different types that are much too complicated without some constraint solver.
I'm working on creating a spec-based validator for creating human-readable error messages. I have a working implementation which locates errors based on the in
key in the returned spec errors for explain-data
. This works fine for errors concerning leaf-level specs, i.e. entries in a collection.
However, I have not yet found a way to create useful error messages for custom predicates that concern a whole collection. Is there a (built-in or custom) way to return some sort of metadata from a custom spec predicate, which could be accessed in the spec error message?
For example, the error message for this spec is not useful for locating the error, i.e. the duplicate values.
(s/def ::num int?)
(s/def ::list (s/and (s/coll-of ::num) #(apply distinct? %)))
(s/explain-data ::list [1 2 3 1])
I would like to be able to return some custom metadata from (apply distinct? %)
, which would tell me which elements caused the error, and allow to locate the errors precisely. Of course this is not just an error with this particular custom predicate, but all custom predicates. There doesn't seem to be a way to add metadata to the error messages generated by spec.
Is this doable? If it isn't, what kind of a workaround would you suggest for this? I would like to use spec for checking correctness and generate errors based on spec errors.how does it compare to https://github.com/alexanderkiel/phrase ?
I'm actually using phrase to generate end-user friendly errors. The problem is passing additional error-related metadata from custom spec predicates to spec errors (and therefore to phrase).
I'm not convinced you can get helpful error messages from the general form of (s/def ::the-name #(apply distinct? %))
- if you consider that the spec is a one-arg predicate function, it would be hard to see how to determine which entry caused the failure.
For the specific case of duplication, you'd probably need to replay the data or reconstruct it - as spec would only recall the input unless you walk it element by element. Even the inbuilt :distinct
field in (s/every ...)
doesn't seem to know which specific member breaks uniqueness
Can test.check reverse regex specs out of the box?
Is there a built in spec for UUID’s that works in CLJS?
Just need the strings.
The former.
for reference: https://clojure.atlassian.net/browse/CLJ-1925
I think this will work:
(s/def ::uuid-string
(s/with-gen
#(re-find #"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" %)
#(gen/fmap str (gen/uuid))))
Are there any spec power tools for defining large entity maps? Not really sure what I’m looking for - just something more concise if possible.