4 Small Steps Towards Awesome Clojure Docstrings

Through my work on cljdoc I spent a lot of time looking at documentation and implementing code to render documentation. This made me more aware of the various facilities in Clojure documentation generators (codox, cljdoc, ...) and I would like to use this post to share that awareness with the wider Clojure community.

1. Backtick-Quote Function Arguments & Special Keywords

Whenever referring to an argument or special keywords, quote them using Markdown style `backticks`. This makes them stand out more when reading the docstring, making it easier to visually parse and skim. Emacs also nicely highlights this (possibly others too).

(defn conj!
  [coll x]
  "Adds `x` to the transient collection, and return `coll`. The 'addition'
   may happen at different 'places' depending on the concrete type."

2. Link To Other Functions Using [[Wikilink]] Syntax

Functions call each other and sometimes it can be useful to link to other functions. In Codox and cljdoc you can do this by wrapping the var name in wikilink-style double brackets:

(defn unlisten!
  "Removes registered listener from connection. See also [[listen!]]."
  [conn key]
  (swap! (:listeners (meta conn)) dissoc key))

Featured here: datascript.core/unlisten!. To link to vars in other namespaces, fully qualify the symbol in the brackets, e.g. [[datascript.core/listen!]].

3. Include Small Examples

On cljdoc all docstrings are interpreted as Markdown. With Codox this can be achived with a small configuration tweak. This means you have access to all the text formatting facilities that Markdown provides including code blocks. Code blocks can be fantastic when trying to show how a function is used in a bigger context, as very nicely shown in the Keechma Toolbox documentation:

keechma register

See the source of this majestic docstring.

4. Use Tables To Describe Complex Options Maps

cljdoc's Markdown implementation supports tables as well. Those can be very useful when having a function that receives a map of options, like reitit.core/router:

reitit core router

See the source of this beautiful docstring.


These trivial to implement improvements can make your docstrings 1000x times nicer to read (scientific studies have shown). Also they will just look plain awesome on cljdoc. Check out some examplary docstring work done by Nikita Prokopov here:

And please tell me about other projects with exceptional documentation or even more ways to make docstrings awesome.

Other Posts

  1. Sustainable Open Source: Current EffortsJanuary 2018
  2. Maven SnapshotsJune 2017
  3. Requiring Closure NamespacesMay 2017
  4. Simple Debouncing in ClojureScriptApril 2017
  5. Making Remote WorkMarch 2017
  6. Just-in-Time Script Loading With React And ClojureScriptNovember 2016
  7. Props, Children & Component Lifecycle in ReagentMay 2016
  8. Om/Next Reading ListNovember 2015
  9. Parameterizing ClojureScript BuildsAugust 2015
  10. ClojureBridge BerlinJuly 2015
  11. Managing Local and Project-wide Development Parameters in LeiningenJune 2015
  12. Formal Methods at AmazonApril 2015
  13. (lisp keymap)February 2015
  14. CLJSJS - Use Javascript Libraries in Clojurescript With EaseJanuary 2015
  15. Why Boot is Relevant For The Clojure EcosystemNovember 2014
  16. S3-Beam — Direct Upload to S3 with Clojure & ClojurescriptOctober 2014
  17. Patalyze — An Experiment Exploring Publicly Available Patent DataOctober 2014
  18. Running a Clojure Uberjar inside DockerSeptember 2014
  19. Using core.async and Transducers to upload files from the browser to S3September 2014
  20. Emacs & VimJuly 2014
  21. Heroku-like Deployment With Dokku And DigitalOceanMarch 2014
  22. Woodworking MasterclassesFebruary 2014
  23. Early Adopters And Inverted Social ProofFebruary 2014
  24. Living SmallFebruary 2014
  25. Sending You a TelegramJanuary 2014
  26. Running a Marathon, Or NotJanuary 2014
  27. Code SimplicityJanuary 2014
  28. What do we need to know?December 2013
  29. Sculley's DiseaseDecember 2013
  30. A Resurrection PostDecember 2013
  31. A Trip To The USSeptember 2013
  32. Analytics DataApril 2013
  33. Asynchronous CommunicationApril 2013
  34. From Zero to Marathon in Six MonthtsMarch 2013
  35. Git Information in Fish Shell’s PromptDecember 2012
  36. When We Build StuffAugust 2012
  37. Models, Operations, Views and EventsJuly 2012
  38. The Twelve Factor AppJune 2012
  39. Paris And BackMay 2012
  40. A Friend Is Looking For A Summer InternshipMay 2012
  41. Kandan Team ChatMay 2012
  42. Startups, This Is How Design WorksMarch 2012
  43. Entypo Icon SetMarch 2012
  44. Hosting A Static Site On Amazon S3February 2012
  45. Exim4 Fix Wrongly Decoded Mail SubjectJanuary 2012