Hello Clojurists,
I am a beginner with Clojure and making my way through Higginbotham’s CftBT. Here is my newbie question. Suppose I have a function like this
how would I annotate that parameter input-map should be a map that contains a key :important-key?
If it is relevant to the answer, by “annotate” I mean some kind of code decoration so that I can automatically generate (from my code) HTML documentation that will tell the reader that the input-map parameter to myfunc is expected to be a map containing the key :important-key. For my purposes, if this annotation also helps with avoiding run-time bugs (such as a parameter of the wrong type being passed) that is a bonus. For my present purposes, I’m not worried about performance so much (avoiding reflection, etc.) as I am still just learning.
Its a little verbose currently (there are some libs that help reduce the verbosity, and I think they are working on coming up with a less verbose syntax), but as borkdude said, you’d use spec as such:
A less formal, and less verbose alternative way some people use, is:
Just document in it the doc-string like so:
(defn myfunc
"Does something.
`input-map` - a map with required keys `:important-key`
`:important-key` - an id that bla bla"
[input-map]
(input-map :important-key))
And something which is between the two in term of formality which people often use as well is destructuring:
In ten years of Clojure I’ve hardly ever seen :pre/:post conditions used in the wild. I don’t know why they never become popular. I suspect it’s because AssertionError doesn’t play nice with catching an Exception (you need to catch Throwable instead) and so :pre/:post have remained less popular than assert, which also doesn’t seem to be very widely used in the wild.
I do use assert occasionally and very, very occasionally I use :pre/:post. If I want argument validation in a function, I’m much more likely to use an explicit check and then throw an IllegalArgumentException with information about what’s wrong with the argument. I think that’s a much more friendly approach in library code.
I use :pre sometimes when exploring different ways to structure my data (I suspect it’s related to having to work on clojure 1.7 in prod in my last job, where spec was not really an option), and I find it practical, both as “live documentation”, and for debugging.
You should put this information in a human readable docstring. There are many tools to produce HTML API documentation from docstrings, for example cljdoc.