This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-13
Channels
- # beginners (99)
- # boot (2)
- # boot-dev (4)
- # chestnut (2)
- # cider (75)
- # clara (43)
- # cljs-dev (1)
- # cljsjs (6)
- # cljsrn (4)
- # clojars (2)
- # clojure (76)
- # clojure-brasil (1)
- # clojure-france (1)
- # clojure-italy (2)
- # clojure-spec (30)
- # clojure-uk (4)
- # clojurescript (39)
- # core-async (1)
- # core-logic (2)
- # cursive (1)
- # data-science (7)
- # datomic (14)
- # docker (12)
- # emacs (6)
- # fulcro (69)
- # garden (4)
- # hoplon (7)
- # jobs-discuss (46)
- # leiningen (3)
- # lumo (3)
- # off-topic (12)
- # om (2)
- # parinfer (12)
- # perun (9)
- # re-frame (44)
- # reagent (6)
- # rum (1)
- # shadow-cljs (73)
- # specter (5)
- # unrepl (10)
- # vim (2)
The (s/keys :req (conj my-keys ::b))
is treated as (s/keys :req [conj my-keys ::b])
so it requires ::b
but the other two elements are symbols so s/keys
probably doesn't handle them as expected (it certainly does not evaluate them).
Hence, when you supply a map containing ::b
it validates and when it doesn't contain ::b
it is invalid.
I expect that deep within the implementation of s/keys
, the (unevaluated) symbols conj
and my-keys
are processed in such a way that they fail to be treated as keys at all. @kenny
Ah, looking at the source of s/keys
it filters out anything that isn't a keyword:
req-keys (filterv keyword? (flatten req))
req-un-specs (filterv keyword? (flatten req-un))
Then why is this validated correctly?
(def my-keys [::a])
=> #'boot.user/my-keys
(s/def ::a int?)
=> :boot.user/a
(s/valid? (s/keys :req (conj my-keys ::b))
{::a "a"
::b "b"})
=> false
It looks like s/keys
tries to treat anything that isn't a keyword in the sequence supplied to :req
or :req-un
as some sort of predicate but I'm not quite sure I follow all the parts of the macro...
Ah, I see what it's doing with those symbols:
:pred-forms (quote
[(clojure.core/fn [%] (clojure.core/map? %))
(clojure.core/fn [%] clojure.core/conj)
(clojure.core/fn [%] my-keys)
(clojure.core/fn
[%]
(clojure.core/contains? % :user/b))]),
and when you evaluate clojure.core/conj
and my-keys
they evaluate to truthy values (not nil or false).
@kenny Did you read the bit where I said (conj my-keys ::b)
is not evaluated?
It treats that as the key ::b
and two predicates (which are "true").
So your spec is equivalent to (s/keys :req [::b])
Yes, the above :pred-forms
snippet is
Very logical. Not always obvious š
OK, gotta run...
...back š
(s/def ::name string?)
(s/def ::ns string?)
(s/def ::doc (s/nilable string?))
(s/def ::src string?)
(s/def ::type {:var :fn :macro})
(s/def ::line int?)
(s/def ::column int?)
(s/def ::def
(s/keys :req-un [::name ::ns ::doc ::src ::type
::line ::column]))
Trying to sample this spec but getting StackOverflowError
ā is there anything obvious Iām doing wrong?Never mind, I had two specs named ::ns
š
I wrote a blog post about writing specs for URLs: http://conan.is/blogging/a-spec-for-urls-in-clojure.html
@martinklepsch also
(s/def ::type {:var :fn :macro}) ;;->
(s/def ::type #{:var :fn :macro})