This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-21
Channels
- # babashka (16)
- # beginners (182)
- # calva (13)
- # chlorine-clover (43)
- # clj-kondo (17)
- # cljs-dev (14)
- # cljsrn (19)
- # clojure (97)
- # clojure-argentina (7)
- # clojure-dev (45)
- # clojure-europe (7)
- # clojure-germany (5)
- # clojure-nl (4)
- # clojure-portugal (4)
- # clojure-romania (5)
- # clojure-spec (46)
- # clojure-uk (21)
- # clojuredesign-podcast (2)
- # clojurescript (159)
- # conjure (28)
- # core-async (7)
- # cursive (13)
- # datomic (17)
- # defnpodcast (9)
- # duct (1)
- # fulcro (45)
- # graphql (6)
- # jobs (7)
- # jobs-discuss (1)
- # juxt (3)
- # kaocha (4)
- # leiningen (12)
- # malli (5)
- # observability (1)
- # off-topic (50)
- # pathom (15)
- # re-frame (16)
- # reitit (5)
- # remote-jobs (21)
- # ring (7)
- # shadow-cljs (166)
- # test-check (6)
- # tools-deps (27)
- # xtdb (2)
I'm having some trouble with adding a spec for a keyword which is supposed to represent a function. I tried this
(s/fdef ::on-change
:args (s/cat :value :option/id))
(s/def ::props (s/keys :req-un [::options
::value]
:opt-un [::class
::centered?
::on-change
::variant]))
(s/fdef tabs
:args (s/cat :props ::props))
> Var clojure.test.check.properties/for-all* does not exist, clojure.test.check.properties never required
After reading the API docs, it seems fdef
can only take a symbol naming a function.
My question is... how can I create a spec for the function that is passed as :on-change
?
It's funny you ask, I was just arriving to ask something similar. I have a spec describing a map, of which some keys are functions. I'd love to be able to specify that those functions should conform to a given fdef, but not sure how to accomplish that. As is, I just have the keys referring to the functions specced using fn?
use ifn?
not fn?
you can use fspec
to do this as well, but there are some big caveats for generation
personally, I have not found it to be worth doing fspec
over ifn?
@alexmiller Does ifn?
allow you to specify the shape of the arguments that are passed in? I can't seem to find any examples doing so
you can do that with fspec
(same args as fdef
)
Tried a simple fspec
but that doesn't seem to compile. Hmm
(s/fspec ::on-change
:args (s/cat :value number?)
:ret any?)
I get this error when I try that. Is this expected? > Uncaught Error: Var clojure.test.check.properties/for-all* does not exist, clojure.test.check.properties never required
It might be terrible but I recently had a similar issue, went for this solution:
(let [x (expr ...)]
(eval
`(s/def ::my-spec
(s/keys
:req-un
[~x]))))
it is. If you can convince yourself the expr doesn't do any IO then you can sleep well imo
In my case I had to create a qualified keyword who's name starts with a number. seems like :1foo
is a valid kw but :user/1foo
can't be read by the reader. (keyword "user" "1foo")
works
I see the suggestion to use s/assert in docs, but isn't that also something that I should only do in development and not make it part of the code that might be shipped eventually?
Spec asserts can be turned off and even compiled out in prod code
thanks, I realized there has to be some solution because there were blogposts about how to use it, but now I know where to look for it.
Is it possible to spec/validate java collections? this naive example doesn't work
(s/def ::foo int?)
(s/def ::bar string?)
(s/def ::m (s/keys :req [::foo ::bar]))
user=> (s/valid? ::m {::foo 1 ::bar "2"})
true
user=> (s/valid? ::m (java.util.HashMap. {::foo 1 ::bar "2"}))
false
Spec does not cover Java collections so you’d have to pour one into a Clojure collection first
This is probably a terrible idea, but I guess everything is possible if you try hard enough
It would be nice, maybe in spec2, if the meanings of maps and sequences were relaxed a bit. But I'm coming at it from an esoteric use case
that seems way harder than converting the HashMap into a Clojure map
we do not have plans to support Java colls in spec 2
(s/valid? ::m (into {} (java.util.HashMap. {::foo 1 ::bar "2"})))
That's the trivial case, in reality I might be dealing with an arbitrarily nested java collection 😞
It's also unfortunate because it creates a bit of a mismatch between the validation mechanism and the applied predicates. In this example, get
works on java.util.Map
, so does seq, so conform*
can do its work. The only "hurdle" is map?
, which is a pretty stringent requirement. Why not expand spec a bit more towards reflecting intent and less implementation?
the intent is to validate clojure data
validating java colls was out of scope for us
so rephrasing - what function could validate that a map contains at least one true value?
write that function and you're done