I have this spec for a customer (using spec/cat instead of spec/keys for readability reasons):
(ns thrift-store.entities.customer
(:require [clojure.spec.alpha :as s]
[thrift-store.entities.address :refer :all]))
(s/def ::customer
(s/cat
:id uuid?
:name string?
:document string?
:email (s/nilable string?)
:phone-number (s/nilable string?)
:address (s/nilable #(s/map-of ::address %))))
(defn generate-test-customer [name document email phone-number address]
(let [customer {:id (java.util.UUID/randomUUID)
:name name
:document document
:email email
:phone-number phone-number
:address address}]
(if (s/valid? ::customer customer)
customer
(throw (ex-info "Test customer does not conform to the specification"
{:customer customer} (s/explain ::customer customer))))))
(def test-customer (generate-test-customer "Arcles" "86007877000" nil nil test-address))
I get the exception: 'Test customer does not conform to the specification', but isn't the generated customer correct?
Now all the map building functions of my project are no longer working, and are throwing the exceptions, just because I changed spec/keys and countless individual specs to spec/cat and direct specs.
https://github.com/guilhermedjr/thrift-store/commit/a1f625a1aceb2586fdcd3a527cb39089af2bf3ec
Look into docs to see definition and examples for
cat:As you can see,
catdescribes a sequential data structure (vector, list, sequence...),keysdescribes hash-map- they are entirely different and it has nothing to do with readability. When you usecat, the valid customer could look like this:By the way- since version 1.11, Clojure has
random-uuid.EDIT: Are you sure you want to use
(s/nilable #(s/map-of ::address %))?Proper use would be something like
(s/nilable (s/map-of keyword? (s/nilable string?)))... but I think you just want to write:address (s/nilable ::address).