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
2021-04-02T22:21:26.013400Z

(s/def :corp/employee
  (s/keys :req [:employee/first-name]))

(s/def :employee/first-name string?)

(s/def :favorite/ice-cream #{:chocolate :vanilla})

(e/expound :corp/employee {:employee/first-name "michael"
                           :favorite/ice-cream :strawberry})

;; -- Spec failed --------------------

;; {:employee/first-name ...,
;;  :favorite/ice-cream :strawberry}
;; ^^^^^^^^^^^

;; should be one of: :chocolate, :vanilla

;; -- Relevant specs -------

;; :favorite/ice-cream:
;; #{:chocolate :vanilla}
;; :corp/employee:
;; (clojure.spec.alpha/keys :req [:employee/first-name])

;; -------------------------
;; Detected 1 error
I find this pretty surprising

2021-04-02T22:21:57.013900Z

given that the :corp/employee spec doesn't say anything about ice cream

seancorfield 2021-04-02T22:23:56.014500Z

That is by design in Spec — and the reference docs on http://clojure.org talk about that. I think the rationale may do too.

2021-04-02T22:24:28.014600Z

thanks Sean - i'll take a look

seancorfield 2021-04-02T22:25:24.014800Z

https://clojure.org/guides/spec#_entity_maps says “When conformance is checked on a map, it does two things - checking that the required attributes are included, and checking that every registered key has a conforming value. We’ll see later where optional attributes can be useful. Also note that ALL attributes are checked via keys, not just those listed in the :req and :opt keys. Thus a bare (s/keys) is valid and will check all attributes of a map without checking which keys are required or optional.”

2021-04-02T22:29:57.015Z

yeah, there it is. checks that every registered key has a conforming value. good to know