This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-11-02
Channels
- # admin-announcements (1)
- # aws-lambda (9)
- # beginners (161)
- # boot (1)
- # cider (3)
- # cljsrn (36)
- # clojure (245)
- # clojure-austin (2)
- # clojure-denmark (3)
- # clojure-dev (11)
- # clojure-greece (6)
- # clojure-italy (25)
- # clojure-russia (5)
- # clojure-serbia (1)
- # clojure-spec (76)
- # clojure-uk (78)
- # clojurescript (168)
- # clojurex (4)
- # community-development (7)
- # core-async (11)
- # core-logic (5)
- # css (6)
- # cursive (8)
- # data-science (6)
- # datomic (5)
- # devops (4)
- # duct (17)
- # emacs (1)
- # figwheel (8)
- # fulcro (51)
- # hoplon (4)
- # instaparse (3)
- # kekkonen (6)
- # klipse (3)
- # lein-figwheel (9)
- # luminus (2)
- # lumo (3)
- # midje (4)
- # off-topic (11)
- # om (4)
- # onyx (62)
- # other-languages (60)
- # re-frame (21)
- # reagent (63)
- # rum (1)
- # shadow-cljs (22)
- # spacemacs (22)
- # specter (23)
- # test-check (2)
- # vim (2)
- # yada (6)
i have a really basic question...
how do i get
(def foo [:foo/bar]) (spec/def (spec/keys :req foo))
to not throw errors?
Don't know how to create ISeq from: clojure.lang.Symbol
@thedavidmeister That's because spec/keys
is a macro so it doesn't eval its arguments.
hmm, is there a way to get around that?
it would be nice to reuse foo
elsewhere
What problem are you trying to solve?
just generally keeping things DRY
i have a list of keys that i'd like to put in a spec, but also use elsewhere
e.g. putting in a list of options for a dropdown menu
(s/def ::foo (s/keys :req [::foo/bar]))
(last (s/form ::foo))
Try that.hmm yes, that does work but
then if i add :opt
in the positions of things in form change
i.e., make the spec the system of record and get the keys from it elsewhere
yeah i see, is there a more robust way to extract things from spec?
k/v style?
(let [[& {:keys [req req-un opt opt-un]}] (rest (s/form ::some-spec))] ...)
mmm, because (::foo (s/form ::foo))
didn't work
It's just data shrug
The spec should be the system of record tho'...
i don't necessarily see why it should be
and it seems like trying to use it that way is clunky at best
There are JIRA issues around providing a more programmatic API at some point.
Rich is working on a significant spec update that will include more support in this area
no, this is in the internals
if it hasn't been prioritised to date, isn't that evidence against the idea of "should be used in this way"?
Spec is designed for human writing and comprehension right now, not for programmatic writing. But at least it's data so you can programmatically read and comprehend them.
it's true, it's better than nothing atm
i can manually pick apart the form of the spec and alias it to something more convenient
but if the intention is truly that spec is a "one stop shop" for this type of thing, then this API needs some polishing >.<
(::foo (:keys (s/xxx ::foo)))
seems to be what i'm reaching for here
where s/xxx
is not s/form
but something along those lines
I just tried this in the REPL. I think it's clearer:
(let [[& {:keys [req req-un opt opt-un]}] (rest (s/form ::foo))] req)
That will destructure all four possible keys
options.
oh nice
yeah something like that đ
thanks for the help
It won't deal with s/merge
constructs tho'... but what we do is have a bunch of basic specs with s/keys
and those are what we destructure to get the actual keys, and then we s/merge
them for compound specs.
(funnily enough I was writing some code to do exactly this at work today)
And we have other code that uses specs as the basis of CRUD-style data functions too...
i think atm it's pretty good getting things in to spec but not so much getting them back out
actually it would be pretty sweet if i could plug spec straight into my UI
but it seems to not quite be there yet
I think it's mostly a matter of tooling -- a lot of which will come from the community.
totally, i've seen a lot of cool tooling already just lurking in this chat
Given that 1.9 is still in pre-release, not everyone is using it yet, which is holding back tooling.
We have 1.9 Beta 3 in production and we're heavy users of spec but it's all still a bit of an adventure...
yeah i know that hoplon had to make some changes to keep pace with 1.9, and also has started playing around with spec but it's WIP
i imagine it is the same for everyone
Beta 4 broke our code due to removing bigdec?
which was added earlier in 1.9. But it was a small change. We expect to have Beta 4 in production on Monday.
nice đ
well i g2g run some errands
thanks for the help
@seancorfield I was able to create minimal reproduction. This only occurs in cljs. Should I make a ticket for this?
(s/def ::test (s/keys :opt-un [::unspeced-keyword]))
(s/def ::test-fn
(s/fspec :args (s/cat :an-arg ::unspeced-keyword)))
(s/assert ::test-fn (fn [a]))
;; => #object[Error Error: Unable to resolve spec: :cljs.user/unspeced-keyword]
I believe it is. fspecs will be checked by using the :args generator to verify the function can accept those args. In this case itâs trying to generate ::test instances that sometimes include ::unspeced-keyword instances, but it doesnât know how to do that.
or at least thatâs my guess, maybe something else going on
If that works in Clojure but fails in cljs, raise a JIRA issue. If it failed in both I'd say it was related to generators. If it's only failing in cljs, I'm not so sure.
Confirmed it works in Clojure, so that looks like a cljs bug.
How do I use a sequence spec as a function argument? This is what I've tried so far without any luck:
(s/def ::int-then-strings (s/cat :num int? :strs (s/+ string?)))
(defn blah [stuff m]
(first stuff))
(s/fdef blah
:args (s/cat :list-of-int-then-strings ::int-then-strings :map map?))
(stest/instrument)
(s/valid? ::int-then-strings [2 "foo"]) ; => true
(blah [2 "foo"] 3)
;; clojure.lang.ExceptionInfo: Call to #'blah did not conform to spec:
;; In: [0] val: [2 "foo"] fails spec: :int-then-strings at: [:args :list-of-int-thenstrings :num] predicate: int?
;; :clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x37194692 "clojure.spec.alpha$regex_spec_impl$reify__1200@37194692"]
;; :clojure.spec.alpha/value ([2 "foo"] 3)
;; :clojure.spec.alpha/args ([2 "foo"] 3)
(s/def ::int-then-strings (s/spec (s/cat :num int? :strs (s/+ string?))))
(defn blah [stuff m]
(first stuff))
(s/fdef blah
:args (s/cat :list-of-int-then-strings ::int-then-strings :map map?))
(stest/instrument)
(s/valid? ::int-then-strings [2 "foo"]) ; => true
(blah [2 "foo"] {:foo 3})
two changes: your ::int-then-strings
spec wrapped in s/spec
to prevent it from getting âflattenedâ into one big sequence spec, and your test call was invalid according to your spec: it was an integer and not a map
because all regex specs combine to describe a single level of sequential collection. The s/spec forces a boundary such that the outer regex spec includes a collection which has an inner regex spec.
Been getting some problems when using clojure.spec.alpha
, clojure.test.check.generators
, and âs
cljs
compilation.
See issue: https://github.com/clojure-emacs/cider/issues/2104 and minimal repo: https://github.com/xiongtx/reload-error-boot
@alexmiller Is it not recommended to use clojure.test.check.generators
directly when using clojure.spec
? It seems to me thereâs weird interaction b/t the lazy combinators, CLJS compilation, and namespace reloading. I suspect we can avoid this problem by using only clojure.spec.gen.alpha
.
I donât understand the problem - too much tooling and other stuff for me to get it. Shouldnât be any issue with using clojure.test.check.generators directly - thatâs the same thing clojure.spec.gen.alpha is doing, just with a delayed load step.
generators in test.check are records iirc - maybe youâre running into a case where the record is being redefined and the old generators are no longer instances of the new (reloaded) record class?
Good insight! Yes, that seems to be precisely whatâs happening. After a refresh:
(let [spec (s/int-in 0 10)
g (s/gen spec)
h (gen/->Generator (constantly 1))]
(println "clojure.spec.alpha generator's classloader: " (.getClassLoader (type g)))
(println "clojure.test.check.generators generator's classloader: " (.getClassLoader (type h))))
;; clojure.spec.alpha generator's classloader: #object[clojure.lang.DynamicClassLoader 0x73867ca9 clojure.lang.DynamicClassLoader@73867ca9]
;; clojure.test.check.generators generator's classloader: #object[clojure.lang.DynamicClassLoader 0x170397bd clojure.lang.DynamicClassLoader@170397bd]
The problem is that clojure.test.check.generators
was reloaded (and the defrecord
re-evaluated), but the same was not done for the lazy combinators in clojure.spec.gen.alpha
. This is probably b/c clojure.spec.gen.alpha
does not :require
clojure.test.check.generators
, so the dependency tracking in clojure.tools.classpath...
isnât working properly.