This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-29
Channels
- # aws (6)
- # beginners (33)
- # bitcoin (2)
- # boot (22)
- # carry (2)
- # cider (5)
- # clara (21)
- # cljs-dev (115)
- # cljsrn (40)
- # clojure (161)
- # clojure-dev (73)
- # clojure-italy (38)
- # clojure-russia (88)
- # clojure-spec (123)
- # clojure-uk (58)
- # clojurescript (88)
- # core-async (26)
- # cursive (5)
- # datascript (18)
- # datomic (26)
- # hoplon (50)
- # java (2)
- # jobs (1)
- # leiningen (10)
- # lumo (1)
- # off-topic (18)
- # om (9)
- # onyx (26)
- # parinfer (13)
- # pedestal (41)
- # quil (1)
- # re-frame (27)
- # reagent (21)
- # ring-swagger (11)
- # slack-help (3)
- # spacemacs (8)
- # specter (5)
- # sql (42)
- # timbre (1)
- # uncomplicate (7)
- # untangled (3)
- # videos (1)
- # yada (26)
Is the following behavior for s/&
expected?
(s/conform (s/* int?) []) ;; => []
(s/conform (s/& (s/* int?)) []) ;; => nil
AFAIKT, (s/& (s/* ...) ...) [])
always returns nil
no matter what predicates are passed to s/&
.
@harrigan not sure if it is relevant but there was an earlier discussion regarding the difference between s/&
and s/and
I don’t think this is due to the difference between s/&
and s/and
. The actual instance that tripped me up was:
(s/conform (s/& (s/+ int?) #(= 3 (count %))) []) ;; => :clojure.spec.alpha/invalid
(s/conform (s/& (s/* int?) #(= 3 (count %))) []) ;; => nil
(require '[clojure.spec.alpha :as s])
(s/conform (s/& (s/* (fn [i] (prn "pred of " i ) (int? i))) (fn [x] (prn "exec test of " x) (= (count x) 1))) [1])
(s/conform (s/and (s/* (fn [i] (prn "pred of " i ) (int? i))) (fn [x] (prn "exec test of " x) (= (count x) 1))) [1])
(s/conform (s/and (s/* (fn [i] (prn "pred of " i ) (int? i))) (fn [x] (prn "exec test of " x) (= (count x) 0))) [])
(s/conform (s/& (s/* (fn [i] (prn "pred of " i ) (int? i))) (fn [x] (prn "exec test of " x) (= (count x) 0))) [])
This is a bug with s/& where it won't check the extra preds if the empty coll passes
There is a ticket with a patch waiting to go in
@harrigan ^^ I am bad at notification
thanks Alex - any idea about the double 'exec test' on the
(s/conform (s/& (s/* (fn [i] (prn "pred of " i ) (int? i))) (fn [x] (prn "exec test of " x) (= (count x) 1))) [1])
Can happen - there is no guarantee on how many times a predicate may be called
I'd have to spend more time to explain why here
To understand why that is
has anyone noticed multi-spec
being slow to generate values? it also sometimes fails randomly
I’m doing a gen/sample
with a size of 1, and I get ExceptionInfo Couldn't satisfy such-that predicate after 100 tries.
but not always
the spec is a multi-spec
that contains maps with strings, nothing fancy
one of the keys is a multi-spec itself
the such-that
exceptions happen when you have an s/and
somewhere and the generator for the first clause isn't likely to satisfy the remaining clauses
in the worst case the problem is solved by writing a custom generator for the (s/and ...)
(the slow generation is probably a different symptom of the same problem)
the only suspect thing in there was this:
(def email-re #"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}")
(s/def ::email (-> (s/and string? #(re-matches email-re %))
(s/with-gen #(gen'/string-from-regex email-re))))
but I removed it and still got the same behaviour
well that looks like it already has the custom generator
correct
is it possible you're using some higher-level spec that expands to an s/and
?
hm, I think s/merge
might
:thinking_face: that sounds strange
I think I know what it is: I’ve been using this macro to disallow “unknown” keys (I know it’s discouraged):
(defmacro only-keys
[& {:keys [req req-un opt opt-un] :as args}]
`(s/merge (s/keys ~@(apply concat (vec args)))
(s/map-of ~(set (concat req
(map (comp keyword name) req-un)
opt
(map (comp keyword name) opt-un)))
any?)))
I don’t think it plays well with generation
removing it fixed my problem
(it seems)
I would've expected s/and
to be used there instead of s/merge
😕
if that's equivalent, I bet the s/and
would actually generate just fine
since I don't think s/keys
generates any extra keys
I'm having a problem with macro expansion and specs ... sometimes the specs are not checked
specs on macros?
these are specs about the compile-time forms, or the runtime data?
@gfredericks compile-time forms
"load the code in cider" means actually running the test, not just compiling it?
@gfredericks thanks, I’ll give it a try
@l0st3d okay, so if you add (is false "dangit")
as a second assertion in your test, it will fail there but not with the first assertion?
okay, I have no idea then
ok ... @gfredericks ... thanks for your help
spec is my new addiction. how did i ever do front-end development without you, my love?
if i need to build a feature but the backend team is busy and won’t get to an api data endpoint in time, no worries: spec can auto-generate a static api response for me and I can go on my way building the html.
@l0st3d if I were you I would try to reproduce the problem without cider; I assume you've tried restarting the cider process?
yes ... the 3 files I posted above always fail to check macro expansion when run from the terminal using lein
I think I read the whole thing backwards
due to ambiguity of "fail" and "pass" in this case
so it's leiningen that has the problem, not cider
in that case I'd try reproducing the problem using just java -cp ... clojure.main <file>
yeah ... started doing that ... what's the minimal classpath that you need to start a repl with 1.9.0-alpha17?
you could try running lein classpath
and using that
which reminds me that if you have deps in your ~/.lein/profiles.clj
then it can be helpful to turn that stuff off via LEIN_NO_USER_PROFILES=1
computers are terrible
are there any plans to attach doc strings to s/def
s?
It might happen some day https://twitter.com/stuarthalloway/status/867362631216230400
In theory you could hack your own doc registry, but it d be nicer to have this built-in
one other small issue I have is that if I have two namespaces foo.bar.baz
and foo.bar.baz.impl
and I want to add a spec alias for foo.bar.baz
so I can do ::baz/blah
inside foo.bar.baz.impl
there doesn’t appear to be a way to do it when foo.bar.baz
requires …impl
. Basically I’d like a version of alias
that doesn’t require the namespace to be loaded.
not sure if there’s a solution to that one yet… other than fully qualify the keywords
I guess that would also allow you to alias keywords to namespaces which don’t exist — which would also be useful as keywords don’t have to map to namespaces
@rickmoynihan @mpenet yes, Rich, Stu, and I all want this, just haven’t gotten to it yet (and I think it’s trickier than it appears). would be happy to see someone dig in and suggest alternatives to move it forward
@alexmiller: doc strings or aliasing, or both?
that was about doc strings
and other metadata?
on aliasing, Rich has some thoughts on an approach to making keyword aliasing better, but I have not gotten info on it yet
@rickmoynihan maybe. needs someone to dig in to see.
@mpenet where do you put them?
a spec can be a keyword reference to another spec - in that case, there is nowhere to hang meta
I don’t think it’s useful to do so here in this chat, but someone needs to evaluate what the options are. if you want to write something up in the ticket or elsewhere, please do.
off the top of my head some options include: explicit support in the spec protocol, hanging meta off the values in the spec registry, wrapping the values in the spec registry, creating a separate registry for docs or meta
these all have various pros and cons
they need to be checked against all the things that can be specs - sets, pred functions, anon functions, keyword refs to other specs, things that implement the Spec protocol, etc
if other kinds of meta, what are some examples? would some meta be set automatically by spec or is it all custom per use?
all of this stuff needs to be answered
yeah it seems like quite a big job - but spec has a pretty big surface area so not surprising
i’ve looked around at s/conformer
and browsed a bit for conforming data with spec… but it seems like a not-great idea to use spec as a sort of “api parser”. is this correct?
i.e. if a service provides me some json, i can’t really write a spec on the client saying “this is my shape”, then somehow use spec to convert json -> my shape, can I?
The general advice is don’t coerce/transform data via s/conform
unless you intend all potential clients of your spec to need that conversion!
At World Singles, we do some coercion with our API specs, but we already have JSON converted to Clojure data structures as input (using JSON middleware for Ring), and so we only coerce strings to keywords and a few other “minor” things in our specs.
So I’d recommend keeping the JSON -> Clojure data step separate from the Clojure data -> conformed input step.
okay, so considering that advice I guess i will write custom (parse-*-entity)
which converts edn (xformed in a handler) from the wrong shape to edn of the client shape.
would be really neat if there’s a tool similar to spec that handles this, though i’m not really sure what it would look like. the real answer is have a properly shaped api response, but beggars cant be choosers
lwhorton: I made a tutorial where I provide one solution to have coercion on top of specs (without affecting the conformance), check the section "Coercing results with spec" at https://medium.com/@wilkerlucio/implementing-custom-om-next-parsers-f20ca6db1664
thanks for the link. this is a good read regardless of coercing because i don’t know om very well
@lwhorton besides the simple version of coercions on the article, I have code for a more sophisticated one (but no explanations) at: https://gist.github.com/wilkerlucio/08fb5f858a12b86f63c76cf453cd90c0