[spec] Clarify s/every docstring for :kind
Description
Environment
Attachments
- 28 Jun 2017, 04:39 PM
Activity
Alex Miller June 26, 2018 at 5:17 PM
Applied
Daniel Sutton June 7, 2018 at 7:40 PM
I would argue that of resolve, update docstring, and decline, resolve should be the correct choice. The `valid?` is the reference implementation of speccing something. It and `explain` must agree on whether something is valid. It would seem that either `valid?` must be corrected to allow specs there or the docstring changed to only allow predicates and `explain` be modified to agree with `valid?`'s notion of whether something is valid (in this case, disallowing specs for `:kind`).
Francis Avila June 7, 2018 at 6:39 PM
Note that this issue can cause s/valid?
and s/explain
to disagree:
(s/def ::vector vector?)
=> :user/vector
(s/valid? (s/coll-of any? :kind ::vector) [])
=> false
(s/explain (s/coll-of any? :kind ::vector) [])
Success!
=> nil
The s/explain*
codepath will interpret keyword :kind
as a spec, but the s/coll-of
and s/every
macros (maybe every-kv
and map-of
too?) unconditionally create a collection predicate function cpred
which assumes :kind
is a predicate; then in every-impl
s/conform*
consults cpred
but s/explain*
does not and always looks at :kind
directly.
Alex Miller February 14, 2017 at 11:06 PM
Marking vetted to either resolve, update docstring, or decline. Need more info from Rich.
Alex Miller February 14, 2017 at 11:06 PM
Certainly a function like this works (s/every number? :kind #(or (vector? %) (list? %))). The question is whether the s/every doc that states "pred/spec" means only a predicate function or "predicate function OR spec". I'm not sure what the intention was. Certainly the code in every seems to be wrapping the kind into a function and then invoking it in every-impl, so it's not written to accept a spec currently.
Details
Details
Assignee
Reporter
Approval
Patch
Priority

Docstring for `s/every` in the `:kind` option says "a pred/spec that the collection type must satisfy, e.g. vector?" but using a spec for `:kind` will fail:
user=> (s/valid? (s/every number? :kind (s/or :vector vector? :list list?)) []) ClassCastException clojure.spec$or_spec_impl$reify__13891 cannot be cast to clojure.lang.IFn dev/eval44499/fn--44501 (form-init3178965928127409998.clj:22) user=> (pst *e) ClassCastException clojure.spec$or_spec_impl$reify__13903 cannot be cast to clojure.lang.IFn user/eval20/fn--22 (NO_SOURCE_FILE:13) clojure.spec/every-impl/reify--14039 (spec.clj:1225) clojure.spec/valid? (spec.clj:744) clojure.spec/valid? (spec.clj:740)
Proposed: The intent here was just to support a predicate function. Change docstring to say just "pred" rather than "pred/spec".
Patch: clj-2111.patch