clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
misha 2020-06-14T22:35:20.343300Z

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 %))))

sgepigon 2020-06-14T22:38:54.344Z

@misha If you’re using regex specs, you probably want s/& instead of s/and

sgepigon 2020-06-14T22:39:57.344800Z

so (s/& ::my-cat-spec #(< 5 (count %)))

misha 2020-06-14T22:42:24.345600Z

you are probably right about s/&, but I still will have to s/unform

misha 2020-06-14T22:44:18.346600Z

actually, since I apply custom pred to the top spec, it does not seem to matter whether I use s/and or s/&

misha 2020-06-14T22:46:12.347700Z

the reason I hope there is another way, is because I'd like to avoid unform

sgepigon 2020-06-14T22:54:23.348900Z

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]

misha 2020-06-14T22:56:56.349800Z

(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

misha 2020-06-14T23:00:40.352900Z

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/&)

misha 2020-06-14T23:02:19.354200Z

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

sgepigon 2020-06-14T23:03:46.354500Z

I see. Thanks for providing an example.

sgepigon 2020-06-14T23:04:02.354900Z

I believe in spec2 this is “non-flowing s/and

misha 2020-06-14T23:04:28.355800Z

yeah, should have mentioned: need this for spec1 :opieop:

sgepigon 2020-06-14T23:04:55.356400Z

You can modify the latter one to go into the map and count from there if you really want to avoid s/unform

sgepigon 2020-06-14T23:04:57.356700Z

(s/explain 
 (s/& :foo/bar #(->> % :1 count (= 3)))
 [1 2 3])

sgepigon 2020-06-14T23:05:19.357100Z

because you end up putting all the conformed values under the :1 key.

misha 2020-06-14T23:05:54.357500Z

what about

(s/cat :1 (s/+ (s/or :a int?))) :2 string?)
:kappa:

misha 2020-06-14T23:07:27.359Z

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

Aron 2020-06-15T08:29:10.362Z

second that. I will have to do something similar soonish, and I am not even sure where I will begin : )

misha 2020-06-15T09:34:15.362200Z

within this week, I hope

sgepigon 2020-06-14T23:18:56.359300Z

(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"])

🤷 1
sgepigon 2020-06-14T23:19:26.359900Z

Yeah I don’t think there’s a great solution for this now in spec1.

sgepigon 2020-06-14T23:20:20.360300Z

s/unform might be your best bet.

misha 2020-06-14T23:22:04.360500Z

but what if it is just int? instead of s/cat ? :troll:

misha 2020-06-14T23:22:37.360900Z

so far, it seems very much like it, yes

sgepigon 2020-06-14T23:22:44.361100Z

lol yeah

sgepigon 2020-06-14T23:24:13.361300Z

FWIW here’s the non-flowing s/and I mentioned: https://github.com/clojure/spec-alpha2/wiki/Differences-from-spec.alpha#nonflowing-sand--new

👍 1
misha 2020-06-14T23:33:23.361600Z

thanks!