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
jrwdunham 2020-03-04T03:53:35.096900Z

Are there best practices for how specs are intended to be identified with one another? I have the situation where I want to define spec ::data via (s/def ::data ::specs/jsonb) (where (s/def ::jsonb map?)). I want to define a map (`spec-casters`) from specs to the functions that can be executed to transform their values (for db insertion). The spec-casters-YES-PLEASE function (which I want to use) seems to do what I want, but I have already run into situations in development where (get spec-casters-YES-PLEASE (s/spec ::other-ns/data)) ;; => nil. I could use spec-casters-NO-THANKS but I would rather avoid that verbosity. This makes me wonder consider that there might be something inadvisable about this approach.

(def spec-casters-YES-PLEASE
  {(s/spec ::specs/jsonb) pg-cast-jsonb})
(def spec-casters-NO-THANKS
  {::specs/jsonb pg-cast-jsonb
   ::other-ns/data pg-cast-jsonb})

alexmiller 2020-03-04T04:01:18.097700Z

I only understand about 30% of what you're trying to do, but (s/spec ::specs/jsonb) is a spec object without well-defined equality semantics so it seems like a bad choice for a key

jrwdunham 2020-03-04T04:09:49.098900Z

Ok, the fact that specs lack well-defined equality semantics suggests that I should just be more explicit and use the NO-THANKS approach where the keys are just the namespaced keywords.

jrwdunham 2020-03-04T04:10:57.099900Z

However, that seems to violate the intention of a key spec though, namely that its value should conform to it ...

alexmiller 2020-03-04T04:11:49.100100Z

but you're not conforming

alexmiller 2020-03-04T04:14:46.100300Z

you're just matching spec objects

alexmiller 2020-03-04T04:15:04.100600Z

not using them for anything

jrwdunham 2020-03-04T04:17:57.100900Z

right, that's true.