This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-30
Channels
- # aws (5)
- # aws-lambda (2)
- # beginners (29)
- # boot (5)
- # cider (3)
- # cljs-dev (3)
- # cljsjs (2)
- # clojure (112)
- # clojure-austin (1)
- # clojure-brasil (2)
- # clojure-italy (9)
- # clojure-nl (2)
- # clojure-russia (5)
- # clojure-spec (49)
- # clojure-uk (41)
- # clojurescript (157)
- # core-logic (5)
- # crypto (1)
- # cursive (12)
- # data-science (38)
- # datomic (31)
- # emacs (3)
- # events (2)
- # garden (3)
- # graphql (10)
- # immutant (4)
- # jobs (3)
- # juxt (5)
- # klipse (1)
- # luminus (3)
- # off-topic (40)
- # om (1)
- # onyx (39)
- # other-languages (7)
- # protorepl (3)
- # re-frame (40)
- # reagent (60)
- # ring (8)
- # ring-swagger (14)
- # shadow-cljs (159)
- # spacemacs (1)
- # specter (6)
- # uncomplicate (3)
- # yada (2)
I poked around with the idea of phrase and i’m not sure it make sense for what i’m doing. As @seancorfield suggested i can pull the information with explain-data
.
And if i want to reference something inside the spec it might make sense to pull it into a var to use across multiple domains rather then pulling it out via regex matching (which is what phrase seems to do).
I’m would be interested to hear how something like phrase worked in a larger project, as it seems prescriptive.
@mpenet What’s your use case? Do you want to browse specs at dev time, or, say, publish specs online similar to API docs?
i know of https://github.com/jpmonettas/inspectable but i d like to ship a browser based thing
Hm, not that I know of. On a related note, I wonder if it’s be useful to start a wiki that collects these spec helper libraries as a resource
@drewverlee I’ve been working on something like this which tries to map a human readable message by a problem’s spec keyword, and falls back to a symbolic predicate match (like Phrase) if it can’t. Trying to embloginate it now.
I was thinking this over last night. I don’t think there is any generic relationship between a human readable message and the code. The only way i could see to do this that was better then plain old clojure would be some sort of semantic analysis of the function words. I feel like a neural net might be able to make something out of the function names and values. I was curious about phrase, but felt it wasn’t doing much for me that i couldn’t get from core spec and a mapping to human readable message. I’m curious about your work.
I suspect its there, but I’m not even close to finding it. My work is mostly a straight dispatch based on the problem’s spec keyword, falling back to a non-macro based Phrase implementation if that fails. And only the latter out of necessity. s/keys specs for example, generate problems that really require you to look at the predicate to know exactly what went wrong.
So the predicate dispatch is mostly to catch cases where :via just doesn’t tell you enough (in the s/keys case, I mean the exact field) about what went wrong.
I’m hoping that approach casts a wide enough net to handle most of the problems generated by our specs. Chopping the specs up, and def’ing each piece seems to help.
I think dispatching on the problem spec’s keyword and maybe some context importer to the end user might make sense. The advantage to just handing them as data and passing them around is that you could organize your code around them.
Is that in line with your thinking? I should get back to you tomorrow when im feeling better.
It’s in use now in a fairly large project, but was introduced only about a month ago. So still waiting to see how it pans out.
Not sure if this is the correct place to ask this question (if not, feel free to boot me to another channel!), but I recently stumbled across some performance related things with respect to spec generative testing specifically regarding every
and the :kind
and :into
parameters.
So the spec I had is loosely similar to this:
(s/def ::x (s/every string? :kind vector?))
(time (some-gen-testing ::x))
=> "Elapsed time: 93083.882115 msecs"
(s/def ::x (s/every string? :into []))
(time (some-gen-testing ::x))
=> "Elapsed time: 293.882115 msecs"
As you can see, :into
is orders of magnitude faster than :kind
for generative testing.
My question is this: when should I be using :kind
and when should I be using :into
?Are you using latest spec? This problem has been fixed.
https://dev.clojure.org/jira/browse/CLJ-2171 fixed in spec 0.1.134
I would recommend preferring kind if that’s sufficient
@alexmiller I think you may have linked the wrong JIRA
more better!
@alexmiller looks like there was a very fun dependency error with pedantic being enabled in leinengen. I was pulling alpha17 when my deps required beta2. Rerunning things I got the following (which looks acceptable to me):
(s/def ::x (s/every string? :kind vector?))
(s/def ::y (s/every string? :into []))
(s/def ::n nil?)
(defn xfn
[x]
nil)
(defn yfn
[y]
nil)
(s/fdef
xfn
:args (s/cat :x ::x)
:ret ::n)
(s/fdef
yfn
:args (s/cat :y ::y)
:ret ::n)
(time (tu/stest-w-report `xfn))
(time (tu/stest-w-report `yfn))
(time (tu/stest-w-report `xfn))
"Elapsed time: 974.417512 msecs"
=> true
(time (tu/stest-w-report `yfn))
"Elapsed time: 522.806027 msecs"
=> true
@alexmiller is that voluntary or a leftover https://github.com/clojure/spec.alpha/blob/739c1af56dae621aedf1bb282025a0d676eff713/src/main/clojure/clojure/spec/alpha.clj#L237 ? just lost a bit of time tracking success! spurious messages in logs that where coming from here
the originating code was a bit weird anyway (just calling s/explain-data in a when-let to validate a piece of content and grad the error in one go), but maybe printing here is not something desirable
@mpenet that is what explain does, if you look at the code up above it as full of prs, the default for explain is to print stuff out
You’ll get that if you ask for explain on something valid
Which leads me to why you would do that... :)
The code in question is gone. But since there an if branch in that code for the printing in case of success maybe it's expected people would do that
I'm was wondering if the following is possible with clojure.spec, since I'm not sure if it's one of the use-cases it tries to solve. Let's say we have a user which can have two roles: (s/def ::role #{:admin :normal})
and a admin specific field which is only required when the user is an admin, not a normal user. I currently have: (s/def ::user (s/keys :req [::role] :opt [::admin-specific-field])
, but that's only partially true, since the second key is required depending on the value of ::role
. Anyone have an idea how to spec this? Thanks 🙂 🙂
@taylor Thanks! Didn't catch that for some reason 😄
Hey, considering https://dev.clojure.org/jira/browse/CLJ-2116 is the top two voted ticket for Clojure right now, I thought about this general issue for quite a while last year and as a result wrote a spec that, given a root spec, recursively parses specs into reversed dependency order, to do a spec rewrite to a new root, while replacing certain parts of the spec-tree. The latter algorithm isn't implemented yet, I put it aside for quite a while. It shouldn't be too much work but maybe I'd need to get tools.analyzer into the mix for rewrites of multispecs. And then there was Rich announcing better programmability of specs in his conj keynote. So the question is, is it still worth pursuing this? Any ideas about how deep the rabbit hole might get? I'm aware of some libs doing spec parsing into records etc. but for some reason I'd like to avoid that (you're welcome to convince me). Also I haven't looked into term rewriting at all, but maybe that's what I'm trying to do.
Ah, https://github.com/jpmonettas/inspectable/blob/master/src/inspectable/spec_utils.cljc#L24 is a nice solution for the multispec-problem.