Welcome! Please see the About page for a little more info on how this works.

0 votes
in Spec by
# Spec metadata support

Problem: Currently there is no way to attach metadata to a spec

It would be nice to be able to add a docstring (the primary use case),
or potentially useful information about usage of that spec in different
contexts (static code analyser, custom conversion/coercion, how it
relates to a particular db schema, human readable error message
template, domain specific concerns or even clj.spec itself later, etc...).

In theory one can today create his own meta-data registry and handle
this at the library level, and that's what a few spec related project
already do, but it would be nicer to have a unified/standard way to do
this. By default it would make sense to add support docstrings for a
start. It could take the form of an extra argument of:

;; at least the following two
(s/def ::foo "Something that's a foo" any?)
(s/def ::foo string? {:doc "Something that's a foo" :cassandra-type :varchar})

;; potentially these depending on the implementation
(s/spec #() :gen ... :meta ...)
(with-meta (s/spec ...))

There are a few ways to implement this, with various pros/cons:

* Implement the IMeta protocol:
This seems like the clean approach, meta data would/could be supported
at any Spec level (ex a non registered spec predicate, a Set spec and
so on). The implementation would require a fair amount changes to the
current code tho. Mostly adding a meta parameter to the various
*-spec-impl macros and sugar at `s/def` and derivatives' level.
A tricky part with that approach is that registered specs that reference
another spec are just a "link" (a keyword), so we have nowhere to add
metadata right now.
They could be reified, return a "pointer" to their original spec and hold
metadata at their own level.

* a simple registry (similar to the spec registry, or shared in the main spec registry):
Basically a map of spec-kw -> metadata if in a separate registry, or integrated into the
main registry somehow.
That's the easy approach, only registered spec would be supported, metadata is separated
from the rest, would keep the Spec instances a bit lighter. Spec referencing other specs
could have their own metadata.
As mentioned this could be done in a separate registry or added to a spec value in the main spec

It seems to be the IMeta is probably the better solution, we'd leverage the existing "meta" api.

5 Answers

0 votes
_Comment made by: bronsa_

(s/def ^{:doc "Something that's a foo" :cassandra-type :varchar} ::foo string?) is not valid clojure, you can't add metadata to a keyword
0 votes

Comment made by: mpenet

Changed example as per Nicolas' comment.

0 votes

Comment made by: jafingerhut

Related to (if not a dup of) CLJ-1965

0 votes

Comment made by: alexmiller

This is related to but not the same as CLJ-1965 - the scope here is larger to potentially support any meta.

0 votes
Reference: https://clojure.atlassian.net/browse/CLJ-2194 (reported by mpenet)