This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-15
Channels
- # bangalore-clj (4)
- # beginners (53)
- # boot (7)
- # cider (1)
- # clara (1)
- # cljs-dev (13)
- # clojure (29)
- # clojure-dusseldorf (3)
- # clojure-russia (7)
- # clojure-spec (63)
- # clojure-uk (7)
- # clojurescript (51)
- # css (1)
- # datomic (5)
- # emacs (1)
- # events (1)
- # fulcro (15)
- # hoplon (3)
- # immutant (3)
- # juxt (1)
- # midje (2)
- # off-topic (24)
- # om (1)
- # parinfer (1)
- # portkey (54)
- # re-frame (4)
- # reagent (13)
- # schema (1)
- # shadow-cljs (19)
- # sql (1)
- # testing (37)
- # yada (2)
am I missing something about conformers? I'm confused as to why (s/valid? (s/conformer (fn [_] :clojure.spec/invalid)) nil)
is true
. If the conformer function returns :clojure.spec/invalid
, shouldn't the value be invalid?
ah, it should be clojure.spec.alpha/invalid
or just ::s/invalid
🦆
what exactly is the relationship/difference between clojure.spec.gen.alpha
and clojure.test.check.generators
?
So far, I've found two differences:
1. missing nat
generator in clojure.spec.gen.alpha
2. cannot reference generators directly, but has to call them as functions:
e.g. with clojure.test.check.generators I can do this:
(gens/hash-map
:boolean gens/boolean
;; note: `nat` generator is not in spec
:small-integers (gens/vector gens/nat)
:large-integer gens/large-integer
:double gens/double
:color (gens/elements [:red :green :blue])
:uuid gens/uuid
:string-or-keyword (gens/tuple gens/string gens/keyword))
But with clojure.spec.gen.alpha
I have to do this:
(gen/hash-map
:boolean (gen/boolean)
;; note: `nat` generator is not in spec
:small-integers (gen/vector gens/nat)
:large-integer (gen/large-integer)
:double (gen/double)
:color (gen/elements [:red :green :blue])
:uuid (gen/uuid)
:string-or-keyword (gen/tuple (gen/string) (gen/keyword)))
Related to the 2.) When I actually try to use (gens/double)
it throws an exception so the usage pattern is a bit inconsistent
what kind of exception?
1. Unhandled java.lang.ClassCastException
clojure.test.check.generators.Generator cannot be cast to clojure.lang.IFn
I don't have anything against either approach, I just thought that they behave in the same way O:-)
oh, you mean between the two namespaces it's inconsistent yes absolutely, and that's unfortunate
btw. @gfredericks thanks a lot for the great Conj talk. I missed it at the conference but watched it now. Really useful!
just a small thing. imho, gen/large-integer
doesn't accept min/max options. I had to use gen/large-integer*
(slide 43).
Funny thing is that if you use clojure.spec.gen.alpha/large-integer
it doens't throw an exception but generates wrong data
that's disappointingly error-prone
the other thing is definitely a slide typo 😞
my org-mode⇒beamer workflow is not yet sophisticated enough to automatically verify that the code works
what do people normally do for spec’ing var-args
do they put the whole thing in a s/?
it feels slightly wrong because that means that it’s all or nothing
@stathissideris does s/*
not work?
ok some context: I’m trying to extend spec-provider to support inference of function specs, and when it comes to varargs, if I see an example of a function call where the varargs happen to be 1 "foo"
I’m not sure if I should infer a spec of (s/cat ... :rest (s/? (s/cat :integer integer? :string string?)))
which says that there are up to 2 varargs but they’re both optional
feels like it’s more restrictive than the function signature
if all you know is one example call, I don't think you can know very much at all for sure
agreed…
but even if I get more calls, I’m not sure what’s the “best” spec to infer
for example let’s say I get one more example where the varargs is just 20
does it then become (s/cat ... :rest (s/? (s/cat :integer integer? :string (s/? string?))))
or maybe I always wrap the individual var-args with s/?
because they’re optional
there's no right answer, it's all heuristics
I know 🙂
which I guess means I have no further advice 🙂 those kinds of problems make me just throw up my hands and give up
they are hard, but they make you think hard about idioms and coder expectations
I had to do a lot of that for spec-provider
@gfredericks great talk btw
thanks
what’s the difference between s/alt
and s/or
?
I saw Ambrose used alt
for multiple arities
I’ve always used or
the example here https://clojuredocs.org/clojure.spec/alt makes that a little more obvious
ok, so it’s like with alt you have an implicit s/cat
around each option
I think it's more like all the "regex" spec types (`cat`, alt
, *
, +
, ?
) are specifically meant to specify elements of a sequence. I wouldn't say there's an implicit cat
around alt
or any of the regex specs, they all work on sequences whether you use them alone or in combination
I'm probably missing some context for your use case though? Writing specs for multi-arity functions?
The fdef
docstring has a nice example:
(s/fdef clojure.core/symbol
:args (s/alt :separate (s/cat :ns string? :n string?)
:str string?
:sym symbol?)
:ret symbol?)
ok, but apart from conciseness, what’s the benefit over s/or
in this case?
(Yes, I’m writing specs for multi-arity functions)
(s/fdef clojure.core/symbol
:args (s/or :separate (s/cat :ns string? :n string?)
:str (s/cat :str string?)
:sym (s/cat :sym symbol?))
:ret symbol?)
yeah, it’s longer, but are there any other disadvantages?
Not sure what other disadvantages there might be. The :args
spec isn't just longer with or
, it's more complex. They also produce slightly different output e.g. when incorrectly calling a instrument
ed function
Regex specs compose together to describe a single sequential context and are generally preferred for describing args
Generally it's best to use a top level cat as you will then get a map conformed to component names that you can use in the :fn spec
@U064X3EF3 but are different arities a “single sequential context”?
For any given case, yes
I would actually write that example now as
Sorry, I can't type it all, on the phone
no problem, would be grateful to have your example when you get some time
Use alt for alternatives, ? for optional args, * for varargs etc. you can describe any set of arities I've encountered with a regex spec
alright, thanks
on a bit of tangent: what about keyword args?
Use keys* - that's what it's for
ok, many thanks!