is there a sensible way to specify min/max items count for s/?
s/*
other than function predicate, like?:
(s/and ::my-cat-spec #(< 5 (count (s/unform ::my-cat-spec %))))
@misha If you’re using regex specs, you probably want s/&
instead of s/and
so (s/& ::my-cat-spec #(< 5 (count %)))
you are probably right about s/&, but I still will have to s/unform
actually, since I apply custom pred to the top spec, it does not seem to matter whether I use s/and
or s/&
the reason I hope there is another way, is because I'd like to avoid unform
Hmm I guess I’m still unsure why you need s/unform
. Perhaps there’s something about ::my-cat-spec
I’m missing:
$ clj
Clojure 1.10.1
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (s/def ::points (s/+ int?))
:user/points
user=> (s/conform (s/& ::points #(< 5 (count %))) [0 1 2 3 4 5])
[0 1 2 3 4 5]
(s/def :foo/bar (s/cat :1 (s/+ (s/or :a int?))))
(s/explain
(s/& :foo/bar #(->> % (s/unform :foo/bar) count (= 3)))
[1 2 3])
;Success!
=> nil
(s/explain
(s/& :foo/bar #(->> % count (= 3)))
[1 2 3])
;{:1 [[:a 1] [:a 2] [:a 3]]} - failed: (->> % count (= 3))
=> nil
in your example conformed int it just int, so unforming is identity. but if you have some branchy spec (s/or, s/alt, s/cat) - it will change the shape of the data, so in custom predicates for s/and and s/& you either have to unform, or validate conformed value (but this requires you knowing exactly what kind of spec is as the first arg to s/and
s/&
)
for the homogeneous collections I can use s/coll
and it has :max-count and :min-count options. I was hoping s/cat has something similar
I see. Thanks for providing an example.
I believe in spec2 this is “non-flowing s/and
”
yeah, should have mentioned: need this for spec1 :opieop:
You can modify the latter one to go into the map and count from there if you really want to avoid s/unform
(s/explain
(s/& :foo/bar #(->> % :1 count (= 3)))
[1 2 3])
because you end up putting all the conformed values under the :1
key.
what about
(s/cat :1 (s/+ (s/or :a int?))) :2 string?)
:kappa:the thing is: this is for translating json-schema to clojure spec, so all specs are dynamic, and I don't do this manually. So I need to find the most sane lowest common denominator
second that. I will have to do something similar soonish, and I am not even sure where I will begin : )
within this week, I hope
(defn conformed-count
[conformed]
(->> conformed
vals
(reduce (fn [acc x]
(if (coll? x)
(+ acc (count x))
(inc acc)))
0)))
(s/conform
(s/& :foo/bar #(= 4 (conformed-count %)))
[1 2 3 "blah"])
Yeah I don’t think there’s a great solution for this now in spec1.
s/unform
might be your best bet.
but what if it is just int?
instead of s/cat
? :troll:
so far, it seems very much like it, yes
lol yeah
FWIW here’s the non-flowing s/and
I mentioned: https://github.com/clojure/spec-alpha2/wiki/Differences-from-spec.alpha#nonflowing-sand--new
thanks!