I previously had an api which had a number of functions in it, all of which expected a map in a very particular format. When it came to documenting this API, I found that in the docstrings of each of these functions I was repeating "The map with which this function is called must be of such and such a format, and this field of the map means such and such."
So I thought it would be better for those functions to take a record, and that I could just document the record instead. However it doesn't seem to be possible to document records, at least in any way interpreted either by the doc
macro or Marginalia.
A solution suggested here is "just add a :doc key in the record's meta".
I tried (defrecord ^{:doc "Here is some documentation"} MyRecord [field1 field2])
but macroexpanding this suggests it doesn't have any effect. Also defrecord
returns an instance of java.lang.class
which doesn't implement IMeta so I'm not sure we can give it metadata?
TL;DR: Unfortunately you can't.
From the docs:
Symbols and collections support metadata
When you use defrecord
you are actually creating a java class. Since classes are neither symbols nor Clojure records, you cannot append documentation to them.
More Detailed Explanation
The following REPL session shows why its not possible to append metadata to records.
user=> (defrecord A [a b])
#<Class@61f53f0e user.A>
user=> (meta A) ;; <= A contains no metadata
nil
The important bit to notice here is that A is a regular java class. If you try to set the metadata for A you will get an interesting error
user=> (with-meta A {:doc "Hello"})
ClassCastException java.lang.Class cannot be cast to clojure.lang.IObj
Apparently with-meta expects a clojure.lang.IObj
. Since java.lang.Class
is a a Java-land construct, it clearly knows nothing of clojure.lang.IObj
.
Let's take a look now at the source code for with-meta
user=> (source with-meta)
(def
^{:arglists '([^clojure.lang.IObj obj m])
:doc "Returns an object of the same type and value as obj, with
map m as its metadata."
:added "1.0"
:static true}
with-meta (fn ^:static with-meta [^clojure.lang.IObj x m]
(. x (withMeta m))))
As you can see, this method expects x
to have a withMeta
object, which records clearly don't have.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With