Fork me on GitHub
#clojure-spec
<
2017-04-17
>
xiongtx02:04:40

Is there a plan to make an fn spec part of the fn itself, similar to :pre and :post? As a piece of metadata, maybe?

xiongtx02:04:02

It makes sense to keep contraints on an fn w/ the definition

stathissideris14:04:50

Just released spec-provider, a library that will infer specs from sample data: https://github.com/stathissideris/spec-provider

mobileink16:04:54

Is there any way to attach metadata to a spec? I want to encode json specs like the following in spec:

"n": {"type": "string",
      "readOnly": true,
      "description": "Friendly name of the resource"},

mobileink16:04:00

this is best i’ve come up with, at least it documents it:

(s/def ::n (s/and string?
                  (comment {:read-only true
                            :doc "Friendly name of the resource"})))

mobileink16:04:43

spec works great for e.g. https://github.com/OpenInterConnect/IoTDataModels/blob/master/oic.core.json except for meta props like readOnly.

ikitommi16:04:13

@mobileink there are at least two libs on top of spec which allow meta-data on specs (and produce JSON Schemas): https://github.com/metosin/spec-tools & https://github.com/uswitch/speculate. I’m working on the first one, in which the meta-data is written to spec forms, so the are really persisted. Last PR before releasing, this week hopefully.

mobileink16:04:14

thank you. i did take a brief look at spec-tools and saw some spec->json schema stuff; does it go the other way ’round?

mobileink16:04:21

anyway, i take it that means no way to do it in plain spec?

ikitommi16:04:28

no, just one-way currently. @mpenet had plans of doing the other way around, would open up a whole new level of interop with js.

mobileink16:04:03

so in spec-tools, for readOnly I would do :json-schema/readOnly true?

ikitommi16:04:46

In plain spec, I guess you could add meta-data to registered specs: read the registry value, add meta, re-register.

mobileink16:04:39

yeah, was thinking about that but I think I’ll take the path of least resistance and give spec-tools a try. thanks.

waffletower17:04:44

I am trying to make generative testing of a recursive spec more feasible. Consider the following simple example:

(s/def ::throne string?)
(s/def ::monarch string?)
(s/def ::gold int?)

(def kingdom (s/spec
              (s/keys :req-un [::throne
                               ::monarch
                               ::gold]
                      :opt-un [::kingdoms])))

(s/def ::kingdoms (s/coll-of kingdom))

waffletower17:04:43

Is there an external way to limit the size of the collection produced by s/coll-of, or is a custom generator necessary?

nfisher17:04:34

@waffletower :min-count :max-count allows you to control the collection size.

nfisher17:04:23

(s/def ::kingdoms (s/coll-of ::kingdom :min-count 1 :max-count 10))

nfisher17:04:33

Is that what you’re looking for?

waffletower18:04:46

Thanks! That limits the size supported in the spec though, correct? I am trying to leave the maximum unbounded but place limits to facilitate generation.

waffletower18:04:26

I have tried this route:

(s/def ::kingdoms (s/with-gen
                    (s/coll-of kingdom)
                    (gen/resize 1 (s/gen (s/coll-of kingdom)))))
this often causes an exception which I am currently tracking down:
ClassCastException clojure.test.check.generators.Generator cannot be cast to clojure.lang.IFn  clojure.spec/every-impl/reify--13992 (spec.clj:1285)

Alex Miller (Clojure team)18:04:06

Default is 20 but I find 3 to be better usually

waffletower18:04:34

Thanks Alex, need to slow down to see text like: same options as 'every' 🙂

ikitommi18:04:15

map-of keys don’t get conformed?

(require '[clojure.spec :as s])

(s/conform
  (s/map-of keyword? keyword?)
  {"key" :value})
; :clojure.spec/invalid

(s/conform
  (s/map-of keyword? keyword?)
  {:key :value})
; {:key :value}

(s/conform
  (s/map-of (s/conformer keyword) (s/conformer keyword))
  {"key" "value"})
; {"key" :value}

Alex Miller (Clojure team)18:04:51

no, but you can pass :conform-keys option for that if you need it