{"id":13429677,"url":"https://github.com/bbatsov/clojure-style-guide","last_synced_at":"2025-05-14T15:03:42.454Z","repository":{"id":6196969,"uuid":"7427613","full_name":"bbatsov/clojure-style-guide","owner":"bbatsov","description":"A community coding style guide for the Clojure programming language","archived":false,"fork":false,"pushed_at":"2024-03-06T06:43:57.000Z","size":499,"stargazers_count":4031,"open_issues_count":47,"forks_count":281,"subscribers_count":143,"default_branch":"master","last_synced_at":"2025-04-11T06:15:44.727Z","etag":null,"topics":["clojure","style-guide","styleguide"],"latest_commit_sha":null,"homepage":"https://guide.clojure.style","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bbatsov.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-01-03T18:09:53.000Z","updated_at":"2025-04-04T18:59:51.000Z","dependencies_parsed_at":"2024-01-05T21:52:13.069Z","dependency_job_id":"f41bfb41-2318-4acd-b460-6fcaf95bfdbf","html_url":"https://github.com/bbatsov/clojure-style-guide","commit_stats":{"total_commits":326,"total_committers":70,"mean_commits":"4.6571428571428575","dds":0.6595092024539877,"last_synced_commit":"36ae6b8b126c9d27ac3f92e6e999e69000991de9"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbatsov%2Fclojure-style-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbatsov%2Fclojure-style-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbatsov%2Fclojure-style-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbatsov%2Fclojure-style-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bbatsov","download_url":"https://codeload.github.com/bbatsov/clojure-style-guide/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254168671,"owners_count":22026206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","style-guide","styleguide"],"created_at":"2024-07-31T02:00:43.633Z","updated_at":"2025-05-14T15:03:42.444Z","avatar_url":"https://github.com/bbatsov.png","language":null,"readme":"= The Clojure Style Guide\n:idprefix:\n:idseparator: -\n:sectanchors:\n:sectlinks:\n:toclevels: 1\nifndef::backend-pdf[]\n:toc-title: pass:[\u003ch2\u003eTable of Contents\u003c/h2\u003e]\nendif::[]\n:source-highlighter: rouge\n\n== Introduction\n\n[quote, Officer Alex J. Murphy / RoboCop]\n____\nRole models are important.\n____\n\nifdef::env-github[]\nTIP: You can find a beautiful version of this guide with much improved navigation at https://guide.clojure.style.\nendif::[]\n\nThis Clojure style guide recommends best practices so that real-world Clojure\nprogrammers can write code that can be maintained by other real-world Clojure\nprogrammers. A style guide that reflects real-world usage gets used, and a\nstyle guide that holds to an ideal that has been rejected by the people it is\nsupposed to help risks not getting used at all -- no matter how good it is.\n\nThe guide is separated into several sections of related rules. we've\ntried to add the rationale behind the rules (if it's omitted, we've\nassumed that it's pretty obvious).\n\nWe didn't come up with all the rules out of nowhere; they are mostly\nbased on the experience of the style guide's editors,\nfeedback and suggestions from numerous members of the Clojure community, and\nvarious highly regarded Clojure programming resources, such as\nhttp://www.clojurebook.com/[\"Clojure Programming\"]\nand https://www.manning.com/books/the-joy-of-clojure-second-edition[\"The Joy of Clojure\"].\n\nNothing written here is set in stone.\nThis style guide evolves over time as additional conventions are\nidentified and past conventions are rendered obsolete by changes in\nClojure itself.\n\nNOTE: Clojure's developers also maintain a list of\nhttps://clojure.org/community/contrib_howto#_coding_guidelines[coding\nguidelines for libraries].footnote:[Those guidelines are meant to\nbe applied to Clojure itself and to all the Clojure Contrib libraries.]\nThey were one of the sources of inspiration for the document, you're\ncurrently reading.\n\nifdef::env-github[]\nYou can generate a PDF copy of this guide using https://asciidoctor.org/docs/asciidoctor-pdf/[AsciiDoctor PDF], and an HTML copy https://asciidoctor.org/docs/convert-documents/#converting-a-document-to-html[with] https://asciidoctor.org/#installation[AsciiDoctor] using the following commands:\n\n[source,shell]\n----\n# Generates README.pdf\nasciidoctor-pdf -a allow-uri-read README.adoc\n\n# Generates README.html\nasciidoctor\n----\n\n[TIP]\n====\nInstall the `rouge` gem to get nice syntax highlighting in the generated document.\n\n[source,shell]\n----\ngem install rouge\n----\n====\nendif::[]\n\n=== Guiding Principles\n\n[quote, Harold Abelson, Structure and Interpretation of Computer Programs]\n____\nPrograms must be written for people to read, and only incidentally for machines to execute.\n____\n\nIt's common knowledge that code is read much more often than it is written.\nThe guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Clojure code.\nThey are also meant to reflect real-world usage of Clojure instead of a random ideal. When we had to choose between a very established practice\nand a subjectively better alternative we've opted to recommend the established practice.footnote:[Occasionally we might suggest to the reader to consider some alternatives, though.]\n\nThere are some areas in which there is no clear consensus in the Clojure community regarding a particular style (like semantic indentation vs fixed indentation, semantic comments vs uniform comments, etc).\nIn such scenarios all popular styles are acknowledged and it's up to you to pick one and apply it consistently.\n\nFortunately Clojure is a Lisp, and Lisps are fundamentally\nsimple. Even though this guide was created a few years after Clojure\n(the first version was published in early 2013), you could see that most\nClojure code in the wild was fairly uniform. We attribute this to\nboth the simplicity we already mentioned and to the fact that since day\n1 Clojurists adopted many of the style conventions of other\nestablished Lisp dialects (e.g. Common Lisp and Scheme).  This made\nthe work on this guide fairly easy and straight-forward, especially compared to\nthe massive exercise in frustration that was the\nhttps://rubystyle.guide[Community Ruby Style Guide].footnote:[You'll notice that the Clojure style guide is pretty similar in structure to the Ruby style guide, which served as its main source of inspiration. You'll also notice that the Ruby style guide is much longer, mostly because of the complexity of the Ruby language.]\n\nClojure is famously optimized for simplicity and clarity. We'd like to believe that this guide is going to help you optimize for maximum\nsimplicity and clarity.\n\n=== A Note About Consistency\n\n[quote, Ralph Waldo Emerson]\n____\nA foolish consistency is the hobgoblin of little minds, adored by little statesmen and philosophers and divines.\n____\n\nA style guide is about consistency.footnote:[This section is heavily inspired by Python's PEP-8]\nConsistency with this style guide is important.\nConsistency within a project is more important.\nConsistency within one class or method is the most important.\n\nHowever, know when to be inconsistent -- sometimes style guide recommendations just aren't applicable. When in doubt, use your best judgment.\nLook at other examples and decide what looks best. And don't hesitate to ask!\n\nIn particular: do not break backwards compatibility just to comply with this guide!\n\nSome other good reasons to ignore a particular guideline:\n\n* When applying the guideline would make the code less readable, even for someone who is used to reading code that follows this style guide.\n* To be consistent with surrounding code that also breaks it (maybe for historic reasons) -- although this is also an opportunity to clean up someone else's mess (in true XP style).\n* Because the code in question predates the introduction of the guideline and there is no other reason to be modifying that code.\n* When the code needs to remain compatible with older versions of Clojure that don't support the feature recommended by the style guide.\n\n=== Translations\n\nTranslations of the guide are available in the following languages:\n\n* https://github.com/geekerzp/clojure-style-guide/blob/master/README-zhCN.md[Chinese]\n* https://github.com/ildivan/clojure-style-guide/blob/ita/README.adoc[Italian] (Under progress)\n* https://github.com/totakke/clojure-style-guide/blob/ja/README.adoc[Japanese]\n* https://github.com/kwakbab/clojure-style-guide/blob/master/README-koKO.md[Korean]\n* https://github.com/theSkilled/clojure-style-guide/blob/pt-BR/README.md[Portuguese] (Under progress)\n* https://github.com/Nondv/clojure-style-guide/blob/master/ru/README.md[Russian]\n* https://github.com/jeko2000/clojure-style-guide/blob/master/README.md[Spanish]\n* https://github.com/LeaveNhA/clojure-style-guide/blob/master/README.adoc[Turkish]\n\nNOTE: These translations are not maintained by our editor team, so their quality\nand level of completeness may vary. The translated versions of the guide often\nlag behind the upstream English version.\n\n== Source Code Layout \u0026 Organization\n\n[quote, Jerry Coffin (on indentation)]\n____\nNearly everybody is convinced that every style but their own is\nugly and unreadable. Leave out the \"but their own\" and they're\nprobably right...\n____\n\n[#80-character-limits]\n=== Maximum Line Length [[line-length]]\n\nWhere feasible, avoid making lines longer than 80 characters.\n\n.Why Bother with 80 characters in a World of Modern Widescreen Displays?\n****\n\nA lot of people these days feel that a maximum line length of 80 characters is\njust a remnant of the past and makes little sense today. After all - modern\ndisplays can easily fit 200+ characters on a single line.  Still, there are some\nimportant benefits to be gained from sticking to shorter lines of code.\n\nFirst, and foremost - numerous studies have shown that humans read much faster\nvertically and very long lines of text impede the reading process. As noted\nearlier, one of the guiding principles of this style guide is to optimize the\ncode we write for human consumption.\n\nAdditionally, limiting the required editor window width makes it possible to\nhave several files open side-by-side, and works well when using code review\ntools that present the two versions in adjacent columns.\n\nThe default wrapping in most tools disrupts the visual structure of the code,\nmaking it more difficult to understand. The limits are chosen to avoid wrapping\nin editors with the window width set to 80, even if the tool places a marker\nglyph in the final column when wrapping lines. Some web based tools may not\noffer dynamic line wrapping at all.\n\nSome teams strongly prefer a longer line length. For code maintained exclusively\nor primarily by a team that can reach agreement on this issue, it is okay to\nincrease the line length limit up to 100 characters, or all the way up\nto 120 characters. Please, restrain the urge to go beyond 120 characters.\n****\n\n=== Tabs vs Spaces [[spaces]]\n\nUse *spaces* for indentation. No hard tabs.\n\n=== Body Indentation [[body-indentation]]\n\nUse 2 spaces to indent the bodies of\nforms that have body parameters.  This covers all `def` forms, special\nforms and macros that introduce local bindings (e.g. `loop`, `let`,\n`when-let`) and many macros like `when`, `cond`, `+as-\u003e+`, `+cond-\u003e+`, `case`,\n`with-*`, etc.\n\n[source,clojure]\n----\n;; good\n(when something\n  (something-else))\n\n(with-out-str\n  (println \"Hello, \")\n  (println \"world!\"))\n\n;; bad - four spaces\n(when something\n    (something-else))\n\n;; bad - one space\n(with-out-str\n (println \"Hello, \")\n (println \"world!\"))\n----\n\n=== Function Arguments Alignment [[vertically-align-fn-args]]\n\nVertically align function (macro) arguments spanning multiple lines.\n\n[source,clojure]\n----\n;; good\n(filter even?\n        (range 1 10))\n\n;; bad - argument aligned with function name (one space indent)\n(filter even?\n (range 1 10))\n\n;; bad - two space indent\n(filter even?\n  (range 1 10))\n----\n\nThe reasoning behind this guideline is pretty simple - the arguments are\neasier to process by the human brain if they stand out and stick together.\n\n=== Function Arguments Indentation [[one-space-indent]]\n\nNOTE: Generally, you should stick to the formatting outlined in the previous\nguideline, unless you're limited by the available horizontal space.\n\nUse a single space indentation for function (macro) arguments\nwhen there are no arguments on the same line as the function name.\n\n[source,clojure]\n----\n;; good\n(filter\n even?\n (range 1 10))\n\n(or\n ala\n bala\n portokala)\n\n;; bad - two-space indent\n(filter\n  even?\n  (range 1 10))\n\n(or\n  ala\n  bala\n  portokala)\n----\n\nThis may appear like some weird special rule to people without Lisp background, but the\nreasoning behind it is quite simple. Function calls are\nnothing but regular list literals and normally those are aligned in the same way as\nother collection type literals when spanning multiple lines:\n\n[source,clojure]\n----\n;; list literal\n(1\n 2\n 3)\n\n;; vector literal\n[1\n 2\n 3]\n\n;; set literal\n#{1\n  2\n  3}\n----\n\nAdmittedly, list literals are not very common in Clojure, that's why it's understandable\nthat for many people lists are nothing but an invocation syntax.\n\nAs a side benefit, function arguments are still aligned in this scenario as well. They\njust happen to accidentally be aligned with the function name as well.\n\n.Semantic Indentation vs Fixed Indentation\n****\nThe guidelines to indent differently macros with body forms from\nall other macro and function calls are collectively known as\n\"semantic indentation\". Simply put, this means that the code\nis indented differently, so that the indentation would give the\nreader of the code some hints about its meaning.\n\nThe downside of this approach is that requires Clojure code formatters to be\nsmarter. They either need to process `macro` arglists and rely on the fact\nthat people named their parameters consistently, or process some additional\nindentation metadata.\n\nSome people in the Clojure community have argued that's not worth it and\nthat everything should simply be indented in the same fashion. Here are\na few examples:\n\n[source,clojure]\n----\n;;; Fixed Indentation\n;;\n;; macros\n(when something\n  (something-else))\n\n(with-out-str\n  (println \"Hello, \")\n  (println \"world!\"))\n\n;; function call spanning two lines\n(filter even?\n  (range 1 10))\n\n;; function call spanning three lines\n(filter\n  even?\n  (range 1 10))\n----\n\nThis suggestion has certainly gotten some ground in the community, but it also\ngoes against much of the Lisp tradition and one of the primary goals of this style guide -\nnamely to optimize code for human consumption.\n\nThere's one exception to the fixed indentation rule - data lists (those that are not a function invocation):\n\n[source,clojure]\n----\n;;; Fixed Indentation\n;;\n;; list literals\n;; we still do\n(1\n 2\n 3\n 4\n 5\n 6)\n\n;; and\n(1 2 3\n 4 5 6)\n\n;; instead of\n(1 2 3\n  4 5 6)\n\n;; or\n(1\n  2\n  3\n  4\n  5\n  6)\n----\n\nThis makes sure that lists are consistent with how other collection types are normally indented.\n\n****\n\n=== Bindings Alignment [[bindings-alignment]]\n\nVertically align `let` (and `let`-like) bindings.\n\n[source,clojure]\n----\n;; good\n(let [thing1 \"some stuff\"\n      thing2 \"other stuff\"]\n  (foo thing1 thing2))\n\n;; bad\n(let [thing1 \"some stuff\"\n  thing2 \"other stuff\"]\n  (foo thing1 thing2))\n----\n\n=== Map Keys Alignment [[map-keys-alignment]]\n\nAlign vertically map keys.\n\n[source,clojure]\n----\n;; good\n{:thing1 thing1\n :thing2 thing2}\n\n;; bad\n{:thing1 thing1\n:thing2 thing2}\n\n;; bad\n{:thing1 thing1\n  :thing2 thing2}\n----\n\n=== Line Endings [[crlf]]\n\nUse Unix-style line endings.footnote:[*BSD/Solaris/Linux/macOS users are\ncovered by default, Windows users have to be extra careful.]\n\n[TIP]\n====\nIf you're using Git you might want to add the following\nconfiguration setting to protect your project from Windows line\nendings creeping in:\n\n[source,shell]\n----\n$ git config --global core.autocrlf true\n----\n====\n\n=== Terminate Files With a Newline [[terminate-files-with-a-newline]]\n\nEnd each file with a newline.\n\nTIP: This should be done by through editor configuration, not manually.\n\n=== Bracket Spacing [[bracket-spacing]]\n\nIf any text precedes an opening bracket(`(`, `{` and\n`[`) or follows a closing bracket(`)`, `}` and `]`), separate that\ntext from that bracket with a space. Conversely, leave no space after\nan opening bracket and before following text, or after preceding text\nand before a closing bracket.\n\n[source,clojure]\n----\n;; good\n(foo (bar baz) quux)\n\n;; bad\n(foo(bar baz)quux)\n(foo ( bar baz ) quux)\n----\n\n=== No Commas in Sequential Collection Literals [[no-commas-for-seq-literals]]\n\n[quote, Alan Perlis]\n____\nSyntactic sugar causes semicolon cancer.\n____\n\nDon't use commas between the elements of sequential collection literals.\n\n[source,clojure]\n----\n;; good\n[1 2 3]\n(1 2 3)\n\n;; bad\n[1, 2, 3]\n(1, 2, 3)\n----\n\n=== Optional Commas in Map Literals [[opt-commas-in-map-literals]]\n\nConsider enhancing the readability of map literals via judicious use\nof commas and line breaks.\n\n[source,clojure]\n----\n;; good\n{:name \"Bruce Wayne\" :alter-ego \"Batman\"}\n\n;; good and arguably a bit more readable\n{:name \"Bruce Wayne\"\n :alter-ego \"Batman\"}\n\n;; good and arguably more compact\n{:name \"Bruce Wayne\", :alter-ego \"Batman\"}\n----\n\n=== Gather Trailing Parentheses [[gather-trailing-parens]]\n\nPlace trailing parentheses on a single line instead of distinct lines.\n\n[source,clojure]\n----\n;; good; single line\n(when something\n  (something-else))\n\n;; bad; distinct lines\n(when something\n  (something-else)\n)\n----\n\nAn exception to the rule is a rich comment for REPL-oriented programming,\nlest gathering the comment's closing parenthesis make the last form in the comment harder to use.\nA rich comment's closing parenthesis may be on the next line.\n\n[source,clojure]\n----\n;; good; rich comment ends on the next line\n(comment\n  (range 5)\n  (interpose '* (range 5))\n  (-\u003e\u003e (range 5) (interpose '*))\n  (= *1 *2)\n  )\n----\n\n=== Empty Lines Between Top-Level Forms [[empty-lines-between-top-level-forms]]\n\nUse a single empty line between top-level forms.\n\n[source,clojure]\n----\n;; good\n(def x ...)\n\n(defn foo ...)\n\n;; bad\n(def x ...)\n(defn foo ...)\n\n;; bad\n(def x ...)\n\n\n(defn foo ...)\n----\n\nAn exception to the rule is the grouping of related ``def``s together.\n\n[source,clojure]\n----\n;; good\n(def min-rows 10)\n(def max-rows 20)\n(def min-cols 15)\n(def max-cols 30)\n----\n\n=== No Blank Lines Within Definition Forms [[no-blank-lines-within-def-forms]]\n\nDo not place blank lines in the middle of a function or\nmacro definition.  An exception can be made to indicate grouping of\npairwise constructs as found in e.g. `let` and `cond`, in case those don't\nfit on the same line.\n\n[source,clojure]\n----\n;; good\n(defn fibo-iter\n  ([n] (fibo-iter 0 1 n))\n  ([curr nxt n]\n   (cond\n     (zero? n) curr\n     :else (recur nxt (+' curr nxt) (dec n)))))\n\n;; okay - the line break delimits a cond pair\n(defn fibo-iter\n  ([n] (fibo-iter 0 1 n))\n  ([curr nxt n]\n   (cond\n     (zero? n)\n     curr\n\n     :else\n     (recur nxt (+' curr nxt) (dec n)))))\n\n;; bad\n(defn fibo-iter\n  ([n] (fibo-iter 0 1 n))\n\n  ([curr nxt n]\n   (cond\n     (zero? n) curr\n\n     :else (recur nxt (+' curr nxt) (dec n)))))\n----\n\nOccasionally, it might seem like a good idea to add a blank line\nhere and there in a longer function definition, but if you get to this\npoint you should also consider whether this long function isn't doing\ntoo much and could potentially be broken down.\n\n=== No Trailing Whitespace [[no-trailing-whitespace]]\n\nAvoid trailing whitespace.\n\n=== One File per Namespace [[one-file-per-namespace]]\n\nUse one file per namespace and one namespace per file.\n\n[source,clojure]\n----\n;; good\n(ns foo.bar)\n\n;; bad\n(ns foo.bar)\n(ns baz.qux)\n\n;; bad\n(in-ns quux.quuz)\n(in-ns quuz.corge)\n\n;; bad\n(ns foo.bar) or (in-ns foo.bar) in multiple files\n----\n\n== Namespace Declaration\n\n=== No Single Segment Namespaces [[no-single-segment-namespaces]]\n\nAvoid single-segment namespaces.\n\n[source,clojure]\n----\n;; good\n(ns example.ns)\n\n;; bad\n(ns example)\n----\n\nNamespaces exist to disambiguate names. Using a single segment\nnamespace puts you in direct conflict with everyone else using single\nsegment namespaces, thus making it more likely you will conflict with\nanother code base.\n\nIn practice this means that libraries should never use single-segment\nnamespace to avoid namespace conflicts with other libraries.\nWithin your own private app of course, you can do whatever you like.\n\nTIP: It's common practice to use the convention `domain.library-name`\nor `library-name.core` for libraries with a single namespace in them.\nRead on for more coverage of the namespace naming topic.\n\nThere are https://github.com/bbatsov/clojure-style-guide/pull/100[other reasons]\nwhy might want to avoid single-segment namespaces, so you should\nthink long and hard before making any use of them.\n\n=== Namespace Segments Limit [[namespace-segments-limit]]\n\nAvoid the use of overly long namespaces (i.e., more than 5 segments).\n\n=== Comprehensive `ns` Form [[comprehensive-ns-declaration]]\n\nStart every namespace with a comprehensive `ns` form, comprised of\n``refer``s, ``require``s, and ``import``s, conventionally in that order.\n\n[source,clojure]\n----\n(ns examples.ns\n  (:refer-clojure :exclude [next replace remove])\n  (:require [clojure.string :as s :refer [blank?]])\n  (:import java.util.Date))\n----\n\n=== Line Breaks in `ns` [[line-break-ns-declaration]]\n\nWhen there are multiple dependencies, you may want give each one its own line.\nThis facilitates sorting, readability, and cleaner diffs for dependency changes.\n\n[source,clojure]\n----\n;; better\n(ns examples.ns\n  (:require\n   [clojure.string :as s :refer [blank?]]\n   [clojure.set :as set]\n   [clojure.java.shell :as sh])\n  (:import\n   java.util.Date\n   java.text.SimpleDateFormat\n   [java.util.concurrent Executors\n                         LinkedBlockingQueue]))\n\n;; good\n(ns examples.ns\n  (:require [clojure.string :as s :refer [blank?]]\n            [clojure.set :as set]\n            [clojure.java.shell :as sh])\n  (:import java.util.Date\n           java.text.SimpleDateFormat\n           [java.util.concurrent Executors\n                                 LinkedBlockingQueue]))\n\n;; bad\n(ns examples.ns\n  (:require [clojure.string :as s :refer [blank?]] [clojure.set :as set] [clojure.java.shell :as sh])\n  (:import java.util.Date java.text.SimpleDateFormat [java.util.concurrent Executors LinkedBlockingQueue]))\n----\n\n=== Prefer `:require` Over `:use` [[prefer-require-over-use]]\n\nIn the `ns` form prefer `:require :as` over `:require :refer` over `:require\n:refer :all`.  Prefer `:require` over `:use`; the latter form should be\nconsidered deprecated for new code.\n\n[source,clojure]\n----\n;; good\n(ns examples.ns\n  (:require [clojure.zip :as zip]))\n\n;; good\n(ns examples.ns\n  (:require [clojure.zip :refer [lefts rights]]))\n\n;; acceptable as warranted\n(ns examples.ns\n  (:require [clojure.zip :refer :all]))\n\n;; bad\n(ns examples.ns\n  (:use clojure.zip))\n----\n\n=== Sort Requirements and Imports [[sort-requirements-and-imports]]\n\nIn the `ns` form, sort your requirements and imports. This facilitates readability and avoids duplication, especially when the list of required / imported namespaces is very long.\n\n[source,clojure]\n----\n;; good\n(ns examples.ns\n  (:require\n   [baz.core :as baz]\n   [clojure.java.shell :as sh]\n   [clojure.set :as set]\n   [clojure.string :as s :refer [blank?]]\n   [foo.bar :as foo]))\n\n;; bad\n(ns examples.ns\n  (:require\n   [clojure.string :as s :refer [blank?]]\n   [clojure.set :as set]\n   [baz.core :as baz]\n   [foo.bar :as foo]\n   [clojure.java.shell :as sh]))\n----\n\n=== Use Idiomatic Namespace Aliases\n\nMany core Clojure namespaces have idiomatic aliases that you're\nencouraged to use within your projects - e.g. the most common way to\nrequire `clojure.string` is: `[clojure.string :as str]`.\n\nNOTE: This may appear to mask\n`clojure.core.str`, but it doesn't. It's expected that\n`clojure.core/str` and `clojure.string/*` to be used in a namespace as\n`str` and `str/whatever` without conflict.\n\n[source,clojure]\n----\n;; good\n(ns ... (:require [clojure.string :as str] ...)\n\n(str/join ...)\n\n;; not as good - just be idiomatic and use as `str/`\n(ns ... (:require [clojure.string :as string] ...)\n\n(string/join ...)\n----\n\nAs noted in the next section, it's generally considered idiomatic to use\nan alias that is the last segment of the namespace, if that makes it unique,\nor else the two segments, typically dropping redundant parts like `clj` or `core`.\n\nAmongst Clojure's core and Contrib namespaces, the following namespaces have\nidiomatic aliases following that pattern:\n\n|===\n| Namespace | Idiomatic Alias\n| clojure.datafy\n| datafy\n| clojure.edn\n| edn\n| clojure.java.io\n| io\n| clojure.math\n| math\n| clojure.set\n| set\n| clojure.walk\n| walk\n| clojure.zip\n| zip\n| clojure.core.async\n| async\n| clojure.data.csv\n| csv\n| clojure.data.xml\n| xml\n| clojure.tools.cli\n| cli\n|===\n\nThen there are some core and Contrib namespaces that have shorter idiomatic aliases:\n\n|===\n| Namespace | Idiomatic Alias\n| clojure.java.shell\n| sh\n| clojure.pprint\n| pp\n| clojure.spec.alpha\n| s\n| clojure.string\n| str\n| clojure.core.matrix\n| mat\n| clojure.tools.logging\n| log\n| clojure.core.protocols\n| p\n| clojure.core.reducers\n| r\n|===\n\nAnd amongst commonly used community libraries, there are also many that have\nwidely-used, idiomatic aliases for several namespaces:\n\n|===\n| Namespace | Idiomatic Alias\n| cheshire.core\n| json\n| clj-yaml.core\n| yaml\n| clj-http.client\n| http\n| hugsql.core\n| sql\n| java-time\n| time\n| next.jdbc\n| jdbc\n|===\n\n=== A Recipe for Good Namespace Aliases\n\nAbove we covered a handful of popular namespaces and their idiomatic aliases.\nYou might have noticed that those are a bit inconsistent:\n\n* `clojure.string` becomes `str`\n* `clojure.pprint` becomes `pp`\n* `clojure.walk` becomes `walk`\n* `clojure.spec.alpha` becomes `s`\n\nIt's clear that the one thing they have in common is that they aim to be concise, but still carry some meaning (aliasing `clojure.walk` to `w` would\nbe concise, but won't carry much meaning).\n\nBut what to do about all the other namespaces out there that don't have idiomatic aliases? Well, you better be consistent in your approach to deriving aliases for them,\notherwise the people working on a shared Clojure codebase are going to experience a great deal of confusion. Here are a few rules that you should follow.footnote:[These guidelines are based on a https://stuartsierra.com/2015/05/10/clojure-namespace-aliases[blog post] by Stuart Sierra.]\n\n1. Make the alias the same as the namespace name with the leading parts removed.\n+\n[source,clojure]\n----\n(ns com.example.application\n  (:require\n   [clojure.java.io :as io]\n   [clojure.reflect :as reflect]))\n----\n+\n2. Keep enough trailing parts to make each alias unique.\n+\n[source,clojure]\n----\n[clojure.data.xml :as data.xml]\n[clojure.xml :as xml]\n----\n+\nTIP: Yes, namespace aliases can have dots in them. Make good use of them.\n+\n3. Eliminate redundant words such as \"core\" and \"clj\" in aliases.\n+\n[source,clojure]\n----\n[clj-time.core :as time]\n[clj-time.format :as time.format]\n----\n\n=== Use Consistent Namespace Aliases\n\nAcross a project, it's good to be consistent with namespace aliases; e.g., don't require `clojure.string` as `str` in one namespace but `string` in another.\nIf you follow the previous two guidelines you're basically covered, but if you opt for custom namespace aliasing scheme it's still important to apply it\nconsistently within your projects.\n\n== Naming\n\n[quote, Phil Karlton]\n____\nThe only real difficulties in programming are cache invalidation and\nnaming things.\n____\n\n=== Namespace Naming Schemas [[naming-ns-naming-schemas]]\n\nWhen naming namespaces favor the following two schemas:\n\n* `project.module`\n* `organization.project.module`\n\nWhen you're following the `project.module` naming scheme and your project\nhas a single (implementation) namespace it's common to name it `project.core`.\nAvoid the `project.core` name in all other cases, as more informative names\nare always a better idea.\n\n=== Composite Word Namespace Segments [[naming-namespace-composite-segments]]\n\nUse `lisp-case` in composite namespace segments (e.g. `bruce.project-euler`).\n\nNOTE: Many non-Lisp programming communities refer to `lisp-case` as\n`kebab-case`, but we all know that Lisp existed way before kebab\nwas invented.\n\n=== Functions and Variables [[naming-functions-and-variables]]\n\nUse `lisp-case` for function and variable names.\n\n[source,clojure]\n----\n;; good\n(def some-var ...)\n(defn some-fun ...)\n\n;; bad\n(def someVar ...)\n(defn somefun ...)\n(def some_fun ...)\n----\n\n=== Protocols, Records, Structs and Types [[naming-protocols-records-structs-and-types]]\n\nUse `CapitalCase` for protocols, records, structs, and types. (Keep\nacronyms like HTTP, RFC, XML uppercase.)\n\nNOTE: `CapitalCase` is also known as `UpperCamelCase, `CapitalWords`\nand `PascalCase`.\n\n=== Predicate Methods [[naming-predicates]]\n\nThe names of predicate methods (methods that return a boolean value)\nshould end in a question mark\n(e.g., `even?`).\n\n[source,clojure]\n----\n;; good\n(defn palindrome? ...)\n\n;; bad\n(defn palindrome-p ...) ; Common Lisp style\n(defn is-palindrome ...) ; Java style\n----\n\n=== Unsafe Functions [[naming-unsafe-functions]]\n\nThe names of functions/macros that are not safe in STM transactions\nshould end with an exclamation mark (e.g. `reset!`).\n\n=== Conversion Functions [[naming-conversion-functions]]\n\nUse `+-\u003e+` instead of `to` in the names of conversion functions.\n\n[source,clojure]\n----\n;; good\n(defn f-\u003ec ...)\n\n;; not so good\n(defn f-to-c ...)\n----\n\n=== Dynamic Vars [[naming-dynamic-vars]]\n\nUse `*earmuffs*` for things intended for rebinding (ie. are dynamic).\n\n[source,clojure]\n----\n;; good\n(def ^:dynamic *a* 10)\n\n;; bad\n(def ^:dynamic a 10)\n----\n\n=== Constants [[naming-constants]]\n\nDon't use a special notation for constants; everything is assumed a constant\nunless specified otherwise.\n\n[source,clojure]\n----\n;; good\n(def max-size 10)\n\n;; bad\n(def MAX-SIZE 10) ; Java style\n(def +max-size+ 10) ; Common Lisp style, global constant\n(def *max-size* 10) ; Common Lisp style, global variable\n----\n\nNOTE: Famously `\\*clojure-version*` defies this convention, but you should\ntreat this naming choice as a historical oddity and not as an example to\nfollow.\n\n=== Unused Bindings [[naming-unused-bindings]]\n\nUse `+_+` for destructuring targets and formal argument names whose\nvalue will be ignored by the code at hand.\n\n[source,clojure]\n----\n;; good\n(let [[a b _ c] [1 2 3 4]]\n  (println a b c))\n\n(dotimes [_ 3]\n  (println \"Hello!\"))\n\n;; bad\n(let [[a b c d] [1 2 3 4]]\n  (println a b d))\n\n(dotimes [i 3]\n  (println \"Hello!\"))\n----\n\nHowever, when it can help the understanding of your code, it can be useful to explicitly name unused arguments or maps you're destructuring from. In this case, prepend the name with an underscore to explicitly signal that the variable is supposed to be unused.\n\n[source,clojure]\n----\n;; good\n(defn myfun1 [context _]\n (assoc context :foo \"bar\"))\n\n(defn myfun2 [context {:keys [id]}]\n (assoc context :user-id id))\n\n;; better\n(defn myfun1 [context _user]\n (assoc context :foo \"bar\"))\n\n(defn myfun2 [context {:keys [id] :as _user}]\n (assoc context :user-id id))\n----\n\n=== Idiomatic Names [[idiomatic-names]]\n\nFollow ``clojure.core``'s example for idiomatic names like `pred` and `coll`.\n\n* in functions:\n ** `f`, `g`, `h` - function input\n ** `n` - integer input usually a size\n ** `index`, `i` - integer index\n ** `x`, `y` - numbers\n ** `xs` - sequence\n ** `m` - map\n ** `k`, `ks` - key, keys\n ** `v`, `vs` - value, values (as in a key/value pair)\n ** `s` - string input\n ** `re` - regular expression\n ** `sym` - symbol\n ** `coll` - a collection\n ** `pred` - a predicate closure\n ** `\u0026 more` - variadic input\n ** `xf` - xform, a transducer\n ** `ns` - namespacefootnote:[Technically this will shadow the `ns` macro, but it's extremely unlikely you'll ever need it in the body of a function.]\n* in macros:\n ** `expr` - an expression\n ** `body` - a macro body\n ** `binding` - a macro binding vector\n* in methods (when specified in `defprotocol`, `deftype`, `defrecord`, `reify`, etc):\n ** `this` - for the first argument, indicating a reference to the object - or alternatively, a consistent name which describes the object\n\n== Functions\n\n=== Optional New Line After Function Name [[optional-new-line-after-fn-name]]\n\nOptionally omit the new line between the function name and argument\nvector for `defn` when there is no docstring.\n\n[source,clojure]\n----\n;; good\n(defn foo\n  [x]\n  (bar x))\n\n;; good\n(defn foo [x]\n  (bar x))\n\n;; bad\n(defn foo\n  [x] (bar x))\n----\n\n=== Multimethod Dispatch Val Placement [[multimethod-dispatch-val-placement]]\n\nPlace the `dispatch-val` of a multimethod on the same line as the\nfunction name.\n\n[source,clojure]\n----\n;; good\n(defmethod foo :bar [x] (baz x))\n\n(defmethod foo :bar\n  [x]\n  (baz x))\n\n;; bad\n(defmethod foo\n  :bar\n  [x]\n  (baz x))\n\n(defmethod foo\n  :bar [x]\n  (baz x))\n----\n\n=== One-line Functions\n\nOptionally omit the new line between the argument vector and a short\nfunction body.\n\n[source,clojure]\n----\n;; good\n(defn foo [x]\n  (bar x))\n\n;; good for a small function body\n(defn foo [x] (bar x))\n\n;; good for multi-arity functions\n(defn foo\n  ([x] (bar x))\n  ([x y]\n   (if (predicate? x)\n     (bar x)\n     (baz x))))\n\n;; bad\n(defn foo\n  [x] (if (predicate? x)\n        (bar x)\n        (baz x)))\n----\n\n=== Multiple Arity Indentation [[multiple-arity-indentation]]\n\nIndent each arity form of a function definition vertically aligned with its\nparameters.\n\n[source,clojure]\n----\n;; good\n(defn foo\n  \"I have two arities.\"\n  ([x]\n   (foo x 1))\n  ([x y]\n   (+ x y)))\n\n;; bad - extra indentation\n(defn foo\n  \"I have two arities.\"\n  ([x]\n    (foo x 1))\n  ([x y]\n    (+ x y)))\n----\n\n=== Multiple Arity Order [[multiple-arity-order]]\n\nSort the arities of a function\nfrom fewest to most arguments. The common case of multi-arity\nfunctions is that some K arguments fully specifies the function's\nbehavior, and that arities N \u003c K partially apply the K arity, and\narities N \u003e K provide a fold of the K arity over varargs.\n\n[source,clojure]\n----\n;; good - it's easy to scan for the nth arity\n(defn foo\n  \"I have two arities.\"\n  ([x]\n   (foo x 1))\n  ([x y]\n   (+ x y)))\n\n;; okay - the other arities are applications of the two-arity\n(defn foo\n  \"I have two arities.\"\n  ([x y]\n   (+ x y))\n  ([x]\n   (foo x 1))\n  ([x y z \u0026 more]\n   (reduce foo (foo x (foo y z)) more)))\n\n;; bad - unordered for no apparent reason\n(defn foo\n  ([x] 1)\n  ([x y z] (foo x (foo y z)))\n  ([x y] (+ x y))\n  ([w x y z \u0026 more] (reduce foo (foo w (foo x (foo y z))) more)))\n----\n\n=== Function Length [[function-length]]\n\nAvoid functions longer than 10 LOC (lines of code). Ideally, most\nfunctions will be shorter than 5 LOC.\n\n=== Function Positional Parameters Limit [[function-positional-parameter-limit]]\n\nAvoid parameter lists with more than three or four positional parameters.\n\n=== Pre and Post Conditions [[pre-post-conditions]]\n\nPrefer function pre and post conditions to checks inside a function's body.\n\n[source,clojure]\n----\n;; good\n(defn foo [x]\n  {:pre [(pos? x)]}\n  (bar x))\n\n;; bad\n(defn foo [x]\n  (if (pos? x)\n    (bar x)\n    (throw (IllegalArgumentException. \"x must be a positive number!\")))\n----\n\n== Idioms\n\n=== Dynamic Namespace Manipulation [[ns-fns-only-in-repl]]\n\nAvoid the use of namespace-manipulating functions like `require` and\n`refer`. They are entirely unnecessary outside of a REPL\nenvironment.\n\n=== Forward References [[forward-references]]\n\nAvoid forward references.  They are occasionally necessary, but such occasions\nare rare in practice.\n\n=== Declare [[declare]]\n\nUse `declare` to enable forward references when forward references are\nnecessary.\n\n=== Higher-order Functions [[higher-order-fns]]\n\nPrefer higher-order functions like `map` to `loop/recur`.\n\n=== Vars Inside Functions [[dont-def-vars-inside-fns]]\n\nDon't define vars inside functions.\n\n[source,clojure]\n----\n;; very bad\n(defn foo []\n  (def x 5)\n  ...)\n----\n\n=== Shadowing `clojure.core` Names [[dont-shadow-clojure-core]]\n\nDon't shadow `clojure.core` names with local bindings.\n\n[source,clojure]\n----\n;; bad - clojure.core/map must be fully qualified inside the function\n(defn foo [map]\n  ...)\n----\n\n=== Alter Var Binding [[alter-var]]\n\nUse `alter-var-root` instead of `def` to change the value of a var.\n\n[source,clojure]\n----\n;; good\n(def thing 1) ; value of thing is now 1\n; do some stuff with thing\n(alter-var-root #'thing (constantly nil)) ; value of thing is now nil\n\n;; bad\n(def thing 1)\n; do some stuff with thing\n(def thing nil)\n; value of thing is now nil\n----\n\n=== Nil Punning [[nil-punning]]\n\nUse `seq` as a terminating condition to test whether a sequence is\nempty (this technique is sometimes called _nil punning_).\n\n[source,clojure]\n----\n;; good\n(defn print-seq [s]\n  (when (seq s)\n    (prn (first s))\n    (recur (rest s))))\n\n;; bad\n(defn print-seq [s]\n  (when-not (empty? s)\n    (prn (first s))\n    (recur (rest s))))\n----\n\n=== Converting Sequences to Vectors [[to-vector]]\n\nPrefer `vec` over `into` when you need to convert a sequence into a vector.\n\n[source,clojure]\n----\n;; good\n(vec some-seq)\n\n;; bad\n(into [] some-seq)\n----\n\n=== Converting Something to Boolean\n\nUse the `boolean` function if you need to convert something to an actual boolean value (`true` or `false`).\n\n[source,clojure]\n----\n;; good\n(boolean (foo bar))\n\n;; bad\n(if (foo bar) true false)\n----\n\nNOTE: Don't forget that the only values in Clojure that are \"falsey\" are `false` and `nil`. Everything else\nwill evaluate to `true` when passed to the `boolean` function.\n\nYou'll rarely need an actual boolean value in Clojure, but it's useful to know how to obtain one when you do.\n\n=== `when` vs `if` [[when-instead-of-single-branch-if]]\n\nUse `when` instead of `if` with just the truthy branch, as in `(if condition (something...))` or `(if ... (do ...))`.\n\n[source,clojure]\n----\n;; good\n(when pred\n  (foo)\n  (bar))\n\n;; bad\n(if pred\n  (do\n    (foo)\n    (bar)))\n----\n\n=== `if-let` [[if-let]]\n\nUse `if-let` instead of `let` + `if`.\n\n[source,clojure]\n----\n;; good\n(if-let [result (foo x)]\n  (something-with result)\n  (something-else))\n\n;; bad\n(let [result (foo x)]\n  (if result\n    (something-with result)\n    (something-else)))\n----\n\n=== `when-let` [[when-let]]\n\nUse `when-let` instead of `let` + `when`.\n\n[source,clojure]\n----\n;; good\n(when-let [result (foo x)]\n  (do-something-with result)\n  (do-something-more-with result))\n\n;; bad\n(let [result (foo x)]\n  (when result\n    (do-something-with result)\n    (do-something-more-with result)))\n----\n\n=== `if-not` [[if-not]]\n\nUse `if-not` instead of `(if (not ...) ...)`.\n\n[source,clojure]\n----\n;; good\n(if-not pred\n  (foo))\n\n;; bad\n(if (not pred)\n  (foo))\n----\n\n=== `when-not` [[when-not]]\n\nUse `when-not` instead of `(when (not ...) ...)`.\n\n[source,clojure]\n----\n;; good\n(when-not pred\n  (foo)\n  (bar))\n\n;; bad\n(when (not pred)\n  (foo)\n  (bar))\n----\n\n=== `when-not` vs `if-not` [[when-not-instead-of-single-branch-if-not]]\n\nUse `when-not` instead of `(if-not ... (do ...))`.\n\n[source,clojure]\n----\n;; good\n(when-not pred\n  (foo)\n  (bar))\n\n;; bad\n(if-not pred\n  (do\n    (foo)\n    (bar)))\n----\n\n=== `not=` [[not-equal]]\n\nUse `not=` instead of `(not (= ...))`.\n\n[source,clojure]\n----\n;; good\n(not= foo bar)\n\n;; bad\n(not (= foo bar))\n----\n\n=== `printf` [[printf]]\n\nPrefer `printf` over `(print (format ...))`.\n\n[source,clojure]\n----\n;; good\n(printf \"Hello, %s!\\n\" name)\n\n;; ok\n(println (format \"Hello, %s!\" name))\n----\n\n=== Flexible Comparison Functions\n\nWhen doing comparisons, leverage the fact that Clojure's functions `\u003c`,\n`\u003e`, etc. accept a variable number of arguments.\n\n[source,clojure]\n----\n;; good\n(\u003c 5 x 10)\n\n;; bad\n(and (\u003e x 5) (\u003c x 10))\n----\n\n=== Single Parameter Function Literal [[single-param-fn-literal]]\n\nPrefer `%` over `%1` in function literals with only one parameter.\n\n[source,clojure]\n----\n;; good\n#(Math/round %)\n\n;; bad\n#(Math/round %1)\n----\n\n=== Multiple Parameters Function Literal [[multiple-params-fn-literal]]\n\nPrefer `%1` over `%` in function literals with more than one parameter.\n\n[source,clojure]\n----\n;; good\n#(Math/pow %1 %2)\n\n;; bad\n#(Math/pow % %2)\n----\n\n=== No Useless Anonymous Functions [[no-useless-anonymous-fns]]\n\nDon't wrap functions in anonymous functions when you don't need to.\n\n[source,clojure]\n----\n;; good\n(filter even? (range 1 10))\n\n;; bad\n(filter #(even? %) (range 1 10))\n----\n\n=== No Multiple Forms in Function Literals [[no-multiple-forms-fn-literals]]\n\nDon't use function literals if the function body will consist of\nmore than one form.\n\n[source,clojure]\n----\n;; good\n(fn [x]\n  (println x)\n  (* x 2))\n\n;; bad (you need an explicit do form)\n#(do (println %)\n     (* % 2))\n----\n\n=== Anonymous Functions vs `complement`, `comp` and `partial`\n\nPrefer anonymous functions over `complement`, `comp` and `partial`, as this results\nin simpler code most of the time.footnote:[You can read more on the subject https://ask.clojure.org/index.php/8373/when-should-prefer-comp-and-partial-to-anonymous-functions[here].]\n\n==== `complement` [[complement]]\n\n[source,clojure]\n----\n;; good\n(filter #(not (some-pred? %)) coll)\n\n;; okish\n(filter (complement some-pred?) coll)\n----\n\n==== `comp` [[comp]]\n\n[source,clojure]\n----\n;; Assuming `(:require [clojure.string :as str])`...\n\n;; good\n(map #(str/capitalize (str/trim %)) [\"top \" \" test \"])\n\n;; okish\n(map (comp str/capitalize str/trim) [\"top \" \" test \"])\n----\n\n`comp` is quite useful when composing transducer chains, though.\n\n[source,clojure]\n----\n;; good\n(def xf\n  (comp\n    (filter odd?)\n    (map inc)\n    (take 5)))\n----\n\n==== `partial` [[partial]]\n\n[source,clojure]\n----\n;; good\n(map #(+ 5 %) (range 1 10))\n\n;; okish\n(map (partial + 5) (range 1 10))\n----\n\n=== Threading Macros [[threading-macros]]\n\nPrefer the use of the threading macros `+-\u003e+` (thread-first) and `+-\u003e\u003e+`\n(thread-last) to heavy form nesting.\n\n[source,clojure]\n----\n;; good\n(-\u003e [1 2 3]\n    reverse\n    (conj 4)\n    prn)\n\n;; not as good\n(prn (conj (reverse [1 2 3])\n           4))\n\n;; good\n(-\u003e\u003e (range 1 10)\n     (filter even?)\n     (map (partial * 2)))\n\n;; not as good\n(map (partial * 2)\n     (filter even? (range 1 10)))\n----\n\n=== Threading Macros and Optional Parentheses\n\nParentheses are not required when using the threading macros for functions having no argument specified, so use them only when necessary.\n\n[source,clojure]\n----\n;; good\n(-\u003e x fizz :foo first frob)\n\n;; bad; parens add clutter and are not needed\n(-\u003e x (fizz) (:foo) (first) (frob))\n\n;; good, parens are necessary with an arg\n(-\u003e x\n    (fizz a b)\n    :foo\n    first\n    (frob x y))\n----\n\n=== Threading Macros Alignment\n\nThe arguments to the threading macros `+-\u003e+` (thread-first) and `+-\u003e\u003e+`\n(thread-last) should line up.\n\n[source,clojure]\n----\n;; good\n(-\u003e\u003e (range)\n     (filter even?)\n     (take 5))\n\n;; bad\n(-\u003e\u003e (range)\n  (filter even?)\n  (take 5))\n----\n\n=== Default `cond` Branch [[else-keyword-in-cond]]\n\nUse `:else` as the catch-all test expression in `cond`.\n\n[source,clojure]\n----\n;; good\n(cond\n  (neg? n) \"negative\"\n  (pos? n) \"positive\"\n  :else \"zero\")\n\n;; bad\n(cond\n  (neg? n) \"negative\"\n  (pos? n) \"positive\"\n  true \"zero\")\n----\n\n=== `condp` vs `cond` [[condp]]\n\nPrefer `condp` instead of `cond` when the predicate \u0026 expression don't\nchange.\n\n[source,clojure]\n----\n;; good\n(cond\n  (= x 10) :ten\n  (= x 20) :twenty\n  (= x 30) :thirty\n  :else :dunno)\n\n;; much better\n(condp = x\n  10 :ten\n  20 :twenty\n  30 :thirty\n  :dunno)\n----\n\n=== `case` vs `cond/condp` [[case]]\n\nPrefer `case` instead of `cond` or `condp` when test expressions are\ncompile-time constants.\n\n[source,clojure]\n----\n;; good\n(cond\n  (= x 10) :ten\n  (= x 20) :twenty\n  (= x 30) :forty\n  :else :dunno)\n\n;; better\n(condp = x\n  10 :ten\n  20 :twenty\n  30 :forty\n  :dunno)\n\n;; best\n(case x\n  10 :ten\n  20 :twenty\n  30 :forty\n  :dunno)\n----\n\n=== Short Forms In Cond [[short-forms-in-cond]]\n\nUse short forms in `cond` and related.  If not possible give visual\nhints for the pairwise grouping with comments or empty lines.\n\n[source,clojure]\n----\n;; good\n(cond\n  (test1) (action1)\n  (test2) (action2)\n  :else   (default-action))\n\n;; ok-ish\n(cond\n  ;; test case 1\n  (test1)\n  (long-function-name-which-requires-a-new-line\n    (complicated-sub-form\n      (-\u003e 'which-spans multiple-lines)))\n\n  ;; test case 2\n  (test2)\n  (another-very-long-function-name\n    (yet-another-sub-form\n      (-\u003e 'which-spans multiple-lines)))\n\n  :else\n  (the-fall-through-default-case\n    (which-also-spans 'multiple\n                      'lines)))\n----\n\n=== Set As Predicate [[set-as-predicate]]\n\nUse a `set` as a predicate when appropriate.\n\n[source,clojure]\n----\n;; good\n(remove #{1} [0 1 2 3 4 5])\n\n;; bad\n(remove #(= % 1) [0 1 2 3 4 5])\n\n;; good\n(count (filter #{\\a \\e \\i \\o \\u} \"mary had a little lamb\"))\n\n;; bad\n(count (filter #(or (= % \\a)\n                    (= % \\e)\n                    (= % \\i)\n                    (= % \\o)\n                    (= % \\u))\n               \"mary had a little lamb\"))\n----\n\n=== `inc` and `dec` [[inc-and-dec]]\n\nUse `(inc x)` \u0026 `(dec x)` instead of `(+ x 1)` and `(- x 1)`.\n\n=== `pos?` and `neg?` [[pos-and-neg]]\n\nUse `(pos? x)`, `(neg? x)` \u0026 `(zero? x)` instead of `(\u003e x 0)`,\n`(\u003c x 0)` \u0026 `(= x 0)`.\n\n=== `list*` vs `cons` [[list-star-instead-of-nested-cons]]\n\nUse `list*` instead of a series of nested `cons` invocations.\n\n[source,clojure]\n----\n;; good\n(list* 1 2 3 [4 5])\n\n;; bad\n(cons 1 (cons 2 (cons 3 [4 5])))\n----\n\n=== Sugared Java Interop [[sugared-java-interop]]\n\nUse the sugared Java interop forms.\n\n[source,clojure]\n----\n;;; object creation\n;; good\n(java.util.ArrayList. 100)\n\n;; bad\n(new java.util.ArrayList 100)\n\n;;; static method invocation\n;; good\n(Math/pow 2 10)\n\n;; bad\n(. Math pow 2 10)\n\n;;; instance method invocation\n;; good\n(.substring \"hello\" 1 3)\n\n;; bad\n(. \"hello\" substring 1 3)\n\n;;; static field access\n;; good\nInteger/MAX_VALUE\n\n;; bad\n(. Integer MAX_VALUE)\n\n;;; instance field access\n;; good\n(.someField some-object)\n\n;; bad\n(. some-object someField)\n----\n\n=== Compact Metadata Notation For True Flags [[compact-metadata-notation-for-true-flags]]\n\nUse the compact metadata notation for metadata that contains only\nslots whose keys are keywords and whose value is boolean `true`.\n\n[source,clojure]\n----\n;; good\n(def ^:private a 5)\n\n;; bad\n(def ^{:private true} a 5)\n----\n\n=== Private [[private]]\n\nDenote private parts of your code.\n\n[source,clojure]\n----\n;; good\n(defn- private-fun [] ...)\n\n(def ^:private private-var ...)\n\n;; bad\n(defn private-fun [] ...) ; not private at all\n\n(defn ^:private private-fun [] ...) ; overly verbose\n\n(def private-var ...) ; not private at all\n----\n\n=== Access Private Var [[access-private-var]]\n\nTo access a private var (e.g. for testing), use the `@#'some.ns/var` form.\n\n=== Attach Metadata Carefully [[attach-metadata-carefully]]\n\nBe careful regarding what exactly you attach metadata to.\n\n[source,clojure]\n----\n;; we attach the metadata to the var referenced by `a`\n(def ^:private a {})\n(meta a) ;=\u003e nil\n(meta #'a) ;=\u003e {:private true}\n\n;; we attach the metadata to the empty hash-map value\n(def a ^:private {})\n(meta a) ;=\u003e {:private true}\n(meta #'a) ;=\u003e nil\n----\n\n== Data Structures\n\n[quote, Alan J. Perlis]\n____\nIt is better to have 100 functions operate on one data structure\nthan to have 10 functions operate on 10 data structures.\n____\n\n=== Avoid Lists [[avoid-lists]]\n\nAvoid the use of lists for generic data storage (unless a list is\nexactly what you need).\n\n=== Keywords For Hash Keys [[keywords-for-hash-keys]]\n\nPrefer the use of keywords for hash keys.\n\n[source,clojure]\n----\n;; good\n{:name \"Bruce\" :age 30}\n\n;; bad\n{\"name\" \"Bruce\" \"age\" 30}\n----\n\n=== Literal Collection Syntax [[literal-col-syntax]]\n\nPrefer the use of the literal collection syntax where\napplicable. However, when defining sets, only use literal syntax\nwhen the values are compile-time constants.\n\n[source,clojure]\n----\n;; good\n[1 2 3]\n#{1 2 3}\n(hash-set (func1) (func2)) ; values determined at runtime\n\n;; bad\n(vector 1 2 3)\n(hash-set 1 2 3)\n#{(func1) (func2)} ; will throw runtime exception if (func1) = (func2)\n----\n\n=== Avoid Index Based Collection Access [[avoid-index-based-coll-access]]\n\nAvoid accessing collection members by index whenever possible.\n\n=== Keywords as Functions for Map Values Retrieval [[keywords-as-fn-to-get-map-values]]\n\nPrefer the use of keywords as functions for retrieving values from\nmaps, where applicable.\n\n[source,clojure]\n----\n(def m {:name \"Bruce\" :age 30})\n\n;; good\n(:name m)\n\n;; more verbose than necessary\n(get m :name)\n\n;; bad - susceptible to NullPointerException\n(m :name)\n----\n\n=== Collections as Functions [[colls-as-fns]]\n\nLeverage the fact that most collections are functions of their elements.\n\n[source,clojure]\n----\n;; good\n(filter #{\\a \\e \\o \\i \\u} \"this is a test\")\n\n;; bad - too ugly to share\n----\n\n=== Keywords as Functions [[keywords-as-fns]]\n\nLeverage the fact that keywords can be used as functions of a collection.\n\n[source,clojure]\n----\n((juxt :a :b) {:a \"ala\" :b \"bala\"})\n----\n\n=== Avoid Transient Collections [[avoid-transient-colls]]\n\nAvoid the use of transient collections, except for\nperformance-critical portions of the code.\n\n=== Avoid Java Collections [[avoid-java-colls]]\n\nAvoid the use of Java collections.\n\n=== Avoid Java Arrays [[avoid-java-arrays]]\n\nAvoid the use of Java arrays, except for interop scenarios and\nperformance-critical code dealing heavily with primitive types.\n\n== Types \u0026 Records\n\n=== Record Constructors [[record-constructors]]\n\nDon't use the interop syntax to\nconstruct type and record instances.  `deftype` and `defrecord`\nautomatically create constructor functions. Use those instead of\nthe interop syntax, as they make it clear that you're dealing with a\n`deftype` or a `defrecord`. See https://stuartsierra.com/2015/05/17/clojure-record-constructors[this\narticle]\nfor more details.\n\n[source,clojure]\n----\n(defrecord Foo [a b])\n(deftype Bar [a b])\n\n;; good\n(-\u003eFoo 1 2)\n(map-\u003eFoo {:b 4 :a 3})\n(-\u003eBar 1 2)\n\n;; bad\n(Foo. 1 2)\n(Bar. 1 2)\n----\n\nNote that `deftype` doesn't define the `+map-\u003eType+`\n  constructor. It's available only for records.\n\n=== Custom Record Constructors [[custom-record-constructors]]\n\nAdd custom type/record constructors when needed (e.g. to validate\nproperties on record creation). See https://stuartsierra.com/2015/05/17/clojure-record-constructors[this\narticle]\nfor more details.\n\n[source,clojure]\n----\n(defrecord Customer [id name phone email])\n\n(defn make-customer\n  \"Creates a new customer record.\"\n  [{:keys [name phone email]}]\n  {:pre [(string? name)\n         (valid-phone? phone)\n         (valid-email? email)]}\n  (-\u003eCustomer (next-id) name phone email))\n----\n\nFeel free to adopt whatever naming convention or structure you'd like for such custom constructors.\n\n=== Custom Record Constructors Naming [[custom-record-constructors-naming]]\n\nDon't override the auto-generated type/record constructor functions.\nPeople expect them to have a certain behaviour and changing this behaviour\nviolates the principle of least surprise. See https://stuartsierra.com/2015/05/17/clojure-record-constructors[this\narticle]\nfor more details.\n\n[source,clojure]\n----\n(defrecord Foo [num])\n\n;; good\n(defn make-foo\n  [num]\n  {:pre [(pos? num)]}\n  (-\u003eFoo num))\n\n;; bad\n(defn -\u003eFoo\n  [num]\n  {:pre [(pos? num)]}\n  (Foo. num))\n----\n\n== Mutation\n\n=== Refs [[Refs]]\n\n==== `io!` Macro [[refs-io-macro]]\n\nConsider wrapping all I/O calls with the `io!` macro to avoid nasty\nsurprises if you accidentally end up calling such code in a\ntransaction.\n\n==== Avoid `ref-set` [[refs-avoid-ref-set]]\n\nAvoid the use of `ref-set` whenever possible.\n\n[source,clojure]\n----\n(def r (ref 0))\n\n;; good\n(dosync (alter r + 5))\n\n;; bad\n(dosync (ref-set r 5))\n----\n\n==== Small Transactions [[refs-small-transactions]]\n\nTry to keep the size of transactions (the amount of work encapsulated in them)\nas small as possible.\n\n==== Avoid Short Long Transactions With Same Ref [[refs-avoid-short-long-transactions-with-same-ref]]\n\nAvoid having both short- and long-running transactions interacting\nwith the same Ref.\n\n=== Agents [[Agents]]\n\n==== Agents Send [[agents-send]]\n\nUse `send` only for actions that are CPU bound and don't block on I/O\nor other threads.\n\n==== Agents Send Off [[agents-send-off]]\n\nUse `send-off` for actions that might block, sleep, or otherwise tie\nup the thread.\n\n=== Atoms [[Atoms]]\n\n==== No Updates Within Transactions [[atoms-no-update-within-transactions]]\n\nAvoid atom updates inside STM transactions.\n\n==== Prefer `swap!` over `reset!` [[atoms-prefer-swap-over-reset]]\n\nTry to use `swap!` rather than `reset!`, where possible.\n\n[source,clojure]\n----\n(def a (atom 0))\n\n;; good\n(swap! a + 5)\n\n;; not as good\n(reset! a 5)\n----\n\n== Math\n\n=== Prefer `clojure.math` Functions Over Interop [[prefer-clojure-math-over-interop]]\n\nPrefer math functions from `clojure.math` over (Java) interop or rolling your own.\n\n[source,clojure]\n----\n;; good\n(clojure.math/pow 2 5)\n\n;; okish\n(Math/pow 2 5)\n----\n\nThe JDK package `java.lang.Math` provides access to many useful math\nfunctions. Prior to version 1.11, Clojure relied on using these via interop, but this had\nissues with discoverability, primitive performance, higher order application,\nand portability. The new `clojure.math` namespace provides wrapper functions for\nthe methods available in `java.lang.Math` for `long` and `double` overloads with fast\nprimitive invocation.\n\n== Strings\n\n=== Prefer `clojure.string` Functions Over Interop [[prefer-clojure-string-over-interop]]\n\nPrefer string manipulation functions from `clojure.string` over Java interop or rolling your own.\n\n[source,clojure]\n----\n;; good\n(clojure.string/upper-case \"bruce\")\n\n;; bad\n(.toUpperCase \"bruce\")\n----\n\nNOTE: Several new functions were added to `clojure.string` in Clojure\n1.8 (`index-of`, `last-index-of`, `starts-with?`, `ends-with?` and\n`includes?`). You should avoid using those if you need to support\nolder Clojure releases.\n\n== Exceptions\n\n=== Reuse Existing Exception Types [[reuse-existing-exception-types]]\n\nReuse existing exception types. Idiomatic Clojure code -- when it does\nthrow an exception -- throws an exception of a standard type\n(e.g. `java.lang.IllegalArgumentException`,\n`java.lang.UnsupportedOperationException`,\n`java.lang.IllegalStateException`, `java.io.IOException`).\n\n=== Prefer `with-open` Over `finally` [[prefer-with-open-over-finally]]\n\nFavor `with-open` over `finally`.\n\n== Macros\n\n=== Don't Write a Macro If a Function Will Do [[dont-write-macro-if-fn-will-do]]\n\nDon't write a macro if a function will do.\n\n=== Write Macro Usage before Writing the Macro [[write-macro-usage-before-writing-the-macro]]\n\nCreate an example of a macro usage first and the macro afterwards.\n\n=== Break Complicated Macros [[break-complicated-macros]]\n\nBreak complicated macros into smaller functions whenever possible.\n\n=== Macros as Syntactic Sugar [[macros-as-syntactic-sugar]]\n\nA macro should usually just provide syntactic sugar and the core of\nthe macro should be a plain function. Doing so will improve\ncomposability.\n\n=== Syntax Quoted Forms [[syntax-quoted-forms]]\n\nPrefer syntax-quoted forms over building lists manually.\n\n== Common Metadata\n\nIn this section we'll go over some common metadata for namespaces and\nvars that Clojure development tools can leverage.\n\n=== `:added`\n\nThe most common way to document when a public API was added to a\nlibrary is via the `:added` metadata.\n\n[source,clojure]\n----\n(def ^{:added \"0.5\"} foo\n  42)\n\n(ns foo.bar\n  \"A very useful ns.\"\n  {:added \"0.8\"})\n\n(defn ^{:added \"0.5\"} foo\n  (bar))\n----\n\nTIP: If you're into SemVer, it's a good idea to omit the patch version.\nThis means you should use `0.5` instead of `0.5.0`. This applies\nfor all metadata data that's version related.\n\n=== `:changed`\n\nThe most common way to document when a public API was changed in a\nlibrary is via the `:changed` metadata. This metadata makes sense only for\nvars and you should be using it sparingly, as changing the behavior of\na public API is generally a bad idea.\n\nStill, if you decide to do it, it's best to make that clear to the API\nusers.\n\n[source,clojure]\n----\n(def ^{:added \"0.5\"\n       :changed \"0.6\"} foo\n  43)\n----\n\n=== `:deprecated`\n\nThe most common way to mark deprecated public APIs is via the `:deprecated`\nmetadata. Normally you'd use as the value the version in which something\nwas deprecated in case of versioned software (e.g. a library) or simply\n`true` in the case of unversioned software (e.g. some web application).\n\n[source,clojure]\n----\n;;; good\n;;\n;; in case we have a version\n(def ^{:deprecated \"0.5\"} foo\n  \"Use `bar` instead.\"\n  42)\n\n(ns foo.bar\n  \"A deprecated ns.\"\n  {:deprecated \"0.8\"})\n\n(defn ^{:deprecated \"0.5\"} foo\n  (bar))\n\n;; otherwise\n(defn ^:deprecated foo\n  (bar))\n\n;;; bad\n;;\n;; using the docstring to signal deprecation\n(def foo\n  \"DEPRECATED: Use `bar` instead.\"\n  42)\n\n(ns foo.bar\n  \"DEPRECATED: A deprecated ns.\")\n----\n\n=== `:superseded-by`\n\nOften you'd combine `:deprecated` with `:superseded-by`, as there would be\nsome newer API that supersedes whatever got deprecated.\n\nTypically for vars you'll use a non-qualified name if the replacement lives\nin the same namespace, and a fully-qualified name otherwise.\n\n[source,clojure]\n----\n;; in case we have a version\n(def ^{:deprecated \"0.5\"\n       :superseded-by \"bar\"} foo\n  \"Use `bar` instead.\"\n  42)\n\n(ns foo.bar\n  \"A deprecated ns.\"\n  {:deprecated \"0.8\"\n   :superseded-by \"foo.baz\"})\n\n(defn ^{:deprecated \"0.5\"\n        :superseded-by \"bar\"} foo\n  (bar))\n\n;; otherwise\n(defn ^{:deprecated true\n        :superseded-by \"bar\"} foo\n  (bar))\n----\n\nTIP: You can also consider adding `:supersedes` metadata to the newer APIs, basically the inverse of `:superseded-by`.\n\n=== `:see-also`\n\nFrom time to time you might want to point out some related vars/namespaces that the users of your library might be interested in.\nThe most common way to do so would be via the `:see-also` metadata, which takes a vector of related items.\nWhen talking about vars - items in the same namespace don't need to fully qualified.\n\n[source,clojure]\n----\n;; refers to vars in the same ns\n(def ^{:see-also [\"bar\" \"baz\"]} foo\n  \"A very useful var.\"\n  42)\n\n;; refers to vars in some other ns\n(defn ^{:see-also [\"top.bar\" \"top.baz\"]} foo\n  (bar))\n----\n\nNOTE: Many Clojure programming tools will also try to extract references to other vars from the docstring, but it's both\nsimpler and more explicit to use the `:see-also` metadata instead.\n\n=== `:no-doc`\n\nDocumentation tools like https://github.com/weavejester/codox#metadata-options[Codox] like https://github.com/cljdoc/cljdoc/blob/master/doc/userguide/for-library-authors.adoc#hiding-namespaces-vars-in-documentation[cljdoc] recognize `:no-doc` metadata.\nWhen a var or a namespace has `:no-doc` metadata, it indicates to these tools that it should be excluded from generated API docs.\n\nTo exclude an entire namespace from API docs:\n[source,clojure]\n----\n(ns ^:no-doc my-library.impl\n  \"Internal implementation details\")\n\n...\n----\n\nTo exclude vars within a documented namespace:\n[source,clojure]\n----\n(ns my-library.api)\n\n;; private functions do not get documented\n(defn- clearly-private []\n  ...)\n\n;; nor do public functions with :no-doc metadata\n(defn ^:no-doc shared-helper []\n  ...)\n\n;; this function will be documented\n(defn api-fn1\n  \"I am useful to the public\"\n  []\n  ...)\n----\n\n=== Indentation Metadata\n\nUnlike other Lisp dialects, Clojure doesn't have a standard metadata format to specify the indentation of macros.\nCIDER proposed a tool-agnostic https://docs.cider.mx/cider/indent_spec.html[indentation specification] based on metadata in 2015.footnote:[This was first introduced in CIDER 0.10] Here's a simple example:\n\n[source,clojure]\n----\n;; refers to vars in the same ns\n(defmacro with-in-str\n  \"[DOCSTRING]\"\n  {:style/indent 1}\n  [s \u0026 body]\n  ...cut for brevity...)\n----\n\nThis instructs the indentation engine that this is a macro with one ordinary parameter and a body after it.\n\n[source,clojure]\n----\n;; without metadata (indented as a regular function)\n(dop-iin-str some-string\n             foo\n             bar\n             baz)\n\n;; with metadata (indented as macro with one special param and a body)\n(with-in-str some-string\n  foo\n  bar\n  baz)\n----\n\nUnfortunately, as of 2020 there's still no widespread adoption of `:style/indent` and many editors and IDEs would just\nhardcode the indentation rules for common macros.\n\nNOTE: This approach to indentation (\"semantic indentation\") is a contested topic in the Clojure community, due to the\nneed for the additional metadata and tooling support. Despite the long tradition of that approach in the Lisp community\nin general, some people argue to just stop treating functions and macros differently and simply indent everything with a fixed\nindentation. https://tonsky.me/blog/clojurefmt/[This article] is one popular presentation of that alternative approach.\n\n== Comments\n\n[quote, Steve McConnell]\n____\nGood code is its own best documentation. As you're about to add a\ncomment, ask yourself, \"How can I improve the code so that this\ncomment isn't needed?\" Improve the code and then document it to make\nit even clearer.\n____\n\n=== Self-Explanatory Code\n\nEndeavor to make your code as self-explanatory as possible.\nIf you fail to achieve this follow the rest of the guidelines in this section.\n\n=== Heading Comments [[four-semicolons-for-heading-comments]]\n\nWrite heading comments with at least four semicolons. Those typically serve to outline/separate\nmajor section of code, or to describe important ideas. Often you'd have a section comment followed\nby a bunch of top-level comments.\n\n[source,clojure]\n----\n;;;; Section Comment/Heading\n\n;;; Foo...\n;;; Bar...\n;;; Baz...\n----\n\n=== Top-Level Comments [[three-semicolons-for-top-level-comments]]\n\nWrite top-level comments with three semicolons.\n\n[source,clojure]\n----\n;;; I'm a top-level comment.\n;;; I live outside any definition.\n\n(defn foo [])\n----\n\nNOTE: While the classic Lisp tradition dictates the use of `;;;` for\ntop-level comments, you'll find plenty of Clojure code in the wild\nthat's using `;;` or even `;`.\n\n=== Code Fragment (Line) Comments [[two-semicolons-for-code-fragment]]\n\nWrite comments on a particular fragment of code before that fragment\nand aligned with it, using two semicolons.\n\n[source,clojure]\n----\n(defn foo [x]\n  ;; I'm a line/code fragment comment.\n  x)\n----\n\nNOTE: While the classic Lisp tradition dictates the use of `;;` for\nline comments, you'll find plenty of Clojure code in the wild\nthat's using only `;`.\n\n=== Margin (Inline) Comments [[one-semicolon-for-margin-comments]]\n\nWrite margin comments with one semicolon.\n\n[source,clojure]\n----\n(defn foo [x]\n  x ; I'm a line/code fragment comment.\n  )\n----\n\nAvoid using those in situations that would result in hanging closing parentheses.\n\n=== Semicolon Space [[semicolon-space]]\n\nAlways have at least one space between the semicolon\nand the text that follows it.\n\n[source,clojure]\n----\n;;;; Frob Grovel\n\n;;; This section of code has some important implications:\n;;;   1. Foo.\n;;;   2. Bar.\n;;;   3. Baz.\n\n(defn fnord [zarquon]\n  ;; If zob, then veeblefitz.\n  (quux zot\n        mumble             ; Zibblefrotz.\n        frotz))\n----\n\n=== English Syntax [[english-syntax]]\n\nComments longer than a word begin with a capital letter and use\npunctuation. Separate sentences with\nhttps://en.wikipedia.org/wiki/Sentence_spacing[one space].\n\n[source,clojure]\n----\n;; This is a good comment.\n\n;; this is a bad comment\n----\n\nObviously punctuation is not the most important thing about\na comment, but a bit of extra effort results in better experience\nfor the readers of our comments.\n\n=== No Superfluous Comments [[no-superfluous-comments]]\n\nAvoid superfluous comments.\n\n[source,clojure]\n----\n;; bad\n(inc counter) ; increments counter by one\n----\n\n=== Comment Upkeep [[comment-upkeep]]\n\nKeep existing comments up-to-date. An outdated comment is worse than no comment\nat all.\n\n=== `#_` Reader Macro [[dash-underscore-reader-macro]]\n\nPrefer the use of the `#_` reader macro over a regular comment when\nyou need to comment out a particular form.\n\n[source,clojure]\n----\n;; good\n(+ foo #_(bar x) delta)\n\n;; bad\n(+ foo\n   ;; (bar x)\n   delta)\n----\n\n=== Refactor, Don't Comment [[refactor-dont-comment]]\n\n[quote, Russ Olsen]\n____\nGood code is like a good joke - it needs no explanation.\n____\n\nAvoid writing comments to explain bad code. Refactor the code to\nmake it self-explanatory. (\"Do, or do not. There is no try.\" --Yoda)\n\n=== Comment Annotations\n\n==== Annotate Above [[annotate-above]]\n\nAnnotations should usually be written on the line immediately above\nthe relevant code.\n\n[source,clojure]\n----\n;; good\n(defn some-fun\n  []\n  ;; FIXME: Replace baz with the newer bar.\n  (baz))\n\n;; bad\n;; FIXME: Replace baz with the newer bar.\n(defn some-fun\n  []\n  (baz))\n----\n\n==== Annotate Keywords [[annotate-keywords]]\n\nThe annotation keyword is followed by a colon and a space, then a note\ndescribing the problem.\n\n[source,clojure]\n----\n;; good\n(defn some-fun\n  []\n  ;; FIXME: Replace baz with the newer bar.\n  (baz))\n\n;; bad - no colon after annotation\n(defn some-fun\n  []\n  ;; FIXME Replace baz with the newer bar.\n  (baz))\n\n;; bad - no space after colon\n(defn some-fun\n  []\n  ;; FIXME:Replace baz with the newer bar.\n  (baz))\n----\n\n==== Indent Annotations [[indent-annotations]]\n\nIf multiple lines are required to describe the problem, subsequent\nlines should be indented as much as the first one.\n\n[source,clojure]\n----\n;; good\n(defn some-fun\n  []\n  ;; FIXME: This has crashed occasionally since v1.2.3. It may\n  ;;        be related to the BarBazUtil upgrade. (xz 13-1-31)\n  (baz))\n\n;; bad\n(defn some-fun\n  []\n  ;; FIXME: This has crashed occasionally since v1.2.3. It may\n  ;; be related to the BarBazUtil upgrade. (xz 13-1-31)\n  (baz))\n----\n\n==== Sign and Date Annotations [[sign-and-date-annotations]]\n\nTag the annotation with your initials and a date so its relevance can\nbe easily verified.\n\n[source,clojure]\n----\n(defn some-fun\n  []\n  ;; FIXME: This has crashed occasionally since v1.2.3. It may\n  ;;        be related to the BarBazUtil upgrade. (xz 13-1-31)\n  (baz))\n----\n\n==== Rare Margin (EOL) Annotations [[rare-eol-annotations]]\n\nIn cases where the problem is so obvious that any documentation would\nbe redundant, annotations may be left at the end of the offending line\nwith no note. This usage should be the exception and not the rule.\n\n[source,clojure]\n----\n(defn bar\n  []\n  (sleep 100)) ; OPTIMIZE\n----\n\n==== `TODO` [[todo]]\n\nUse `TODO` to note missing features or functionality that should be\nadded at a later date.\n\n==== `FIXME` [[fixme]]\n\nUse `FIXME` to note broken code that needs to be fixed.\n\n==== `OPTIMIZE` [[optimize]]\n\nUse `OPTIMIZE` to note slow or inefficient code that may cause\nperformance problems.\n\n==== `HACK` [[hack]]\n\nUse `HACK` to note \"code smells\" where questionable coding practices\nwere used and should be refactored away.\n\n==== `REVIEW` [[review]]\n\nUse `REVIEW` to note anything that should be looked at to confirm it\nis working as intended. For example: `REVIEW: Are we sure this is how the\nclient does X currently?`\n\n==== Document Custom Annotations [[document-annotations]]\n\nUse other custom annotation keywords if it feels appropriate, but be\nsure to document them in your project's `README` or similar.\n\n== Documentation\n\nDocstrings are the primary way to document Clojure code. Many definition forms\n(e.g. `def`, `defn`, `defmacro`, `ns`)\nsupport docstrings and usually it's a good idea to make good use of them, regardless\nof whether the var in question is something public or private.\n\nIf a definition form doesn't support docstrings directly you can still supply them via\nthe `:doc` metadata attribute.\n\nThis section outlines some of the common conventions and best\npractices for documenting Clojure code.\n\n=== Prefer Docstrings [[prefer-docstrings]]\n\nIf a form supports docstrings directly prefer them over using `:doc` metadata:\n\n[source,clojure]\n----\n;; good\n(defn foo\n  \"This function doesn't do much.\"\n  []\n  ...)\n\n(ns foo.bar.core\n  \"That's an awesome library.\")\n\n;; bad\n(defn foo\n  ^{:doc \"This function doesn't do much.\"}\n  []\n  ...)\n\n(ns ^{:doc \"That's an awesome library.\")\n  foo.bar.core)\n----\n\n=== Docstring Summary [[docstring-summary]]\n\nLet the first line in the docstring be a complete, capitalized\nsentence which concisely describes the var in question. This makes it\neasy for tooling (Clojure editors and IDEs) to display a short a summary of\nthe docstring at various places.\n\n[source,clojure]\n----\n;; good\n(defn frobnitz\n  \"This function does a frobnitz.\n  It will do gnorwatz to achieve this, but only under certain\n  circumstances.\"\n  []\n  ...)\n\n;; bad\n(defn frobnitz\n  \"This function does a frobnitz. It will do gnorwatz to\n  achieve this, but only under certain circumstances.\"\n  []\n  ...)\n----\n\n=== Leverage Markdown in Docstrings [[markdown-docstrings]]\n\nImportant tools such as https://github.com/cljdoc/cljdoc/blob/master/doc/userguide/for-library-authors.adoc#docstrings[cljdoc] support Markdown in docstrings so leverage it for nicely formatted documentation.\n\n[source,clojure]\n----\n;; good\n(defn qzuf-number\n  \"Computes the [Qzuf number](https://wikipedia.org/qzuf) of the `coll`.\n  Supported options in `opts`:\n\n  | key           | description |\n  | --------------|-------------|\n  | `:finite-uni?`| Assume finite universe; default: `false`\n  | `:complex?`   | If OK to return a [complex number](https://en.wikipedia.org/wiki/Complex_number); default: `false`\n  | `:timeout`    | Throw an exception if the computation doesn't finish within `:timeout` milliseconds; default: `nil`\n\n  Example:\n  ```clojure\n  (when (neg? (qzuf-number [1 2 3] {:finite-uni? true}))\n    (throw (RuntimeException. \\\"Error in the Universe!\\\")))\n  ```\"\n  [coll opts]\n  ...)\n----\n\n=== Document Positional Arguments [[document-pos-arguments]]\n\nDocument all positional arguments, and wrap them them with backticks\n(`) so that editors and IDEs can identify them and potentially provide extra\nfunctionality for them.\n\n[source,clojure]\n----\n;; good\n(defn watsitz\n  \"Watsitz takes a `frob` and converts it to a znoot.\n  When the `frob` is negative, the znoot becomes angry.\"\n  [frob]\n  ...)\n\n;; bad\n(defn watsitz\n  \"Watsitz takes a frob and converts it to a znoot.\n  When the frob is negative, the znoot becomes angry.\"\n  [frob]\n  ...)\n----\n\n=== Document References [[document-references]]\n\nWrap any var references in the docstring with ` so that tooling\ncan identify them. Wrap them with `[[..]]` if you want to link to them.\n\n[source,clojure]\n----\n;; good\n(defn wombat\n  \"Acts much like `clojure.core/identity` except when it doesn't.\n  Takes `x` as an argument and returns that. If it feels like it.\n  See also [[kangaroo]].\"\n  [x]\n  ...)\n\n;; bad\n(defn wombat\n  \"Acts much like clojure.core/identity except when it doesn't.\n  Takes `x` as an argument and returns that. If it feels like it.\n  See also kangaroo.\"\n  [x]\n  ...)\n----\n\n=== Docstring Grammar [[docstring-grammar]]\n\nDocstrings should be composed of well-formed English sentences. Every sentence\nshould start with a capitalized word, be grammatically coherent, and end\nwith appropriate punctuation. Sentences should be separated with a single space.\n\n[source,clojure]\n----\n;; good\n(def foo\n  \"All sentences should end with a period (or maybe an exclamation mark).\n  The sentence should be followed by a space, unless it concludes the docstring.\")\n\n;; bad\n(def foo\n  \"all sentences should end with a period (or maybe an exclamation mark).\n  The sentence should be followed by a space, unless it concludes the docstring.\")\n----\n\n=== Docstring Indentation [[docstring-indentation]]\n\nIndent multi-line docstrings by two spaces.\n\n[source,clojure]\n----\n;; good\n(ns my.ns\n  \"It is actually possible to document a ns.\n  It's a nice place to describe the purpose of the namespace and maybe even\n  the overall conventions used. Note how _not_ indenting the docstring makes\n  it easier for tooling to display it correctly.\")\n\n;; bad\n(ns my.ns\n  \"It is actually possible to document a ns.\nIt's a nice place to describe the purpose of the namespace and maybe even\nthe overall conventions used. Note how _not_ indenting the docstring makes\nit easier for tooling to display it correctly.\")\n----\n\n=== Docstring Leading Trailing Whitespace [[docstring-leading-trailing-whitespace]]\n\nNeither start nor end your docstrings with any whitespace.\n\n[source,clojure]\n----\n;; good\n(def foo\n  \"I'm so awesome.\"\n  42)\n\n;; bad\n(def silly\n  \"    It's just silly to start a docstring with spaces.\n  Just as silly as it is to end it with a bunch of them.      \"\n  42)\n----\n\n=== Place Docstring After Function Name [[docstring-after-fn-name]]\n\nWhen adding a docstring -- especially to a function using the above form -- take\ncare to correctly place the docstring after the function name, not after the\nargument vector.  The latter is not invalid syntax and won't cause an error,\nbut includes the string as a form in the function body without attaching it to\nthe var as documentation.\n\n[source,clojure]\n----\n;; good\n(defn foo\n  \"docstring\"\n  [x]\n  (bar x))\n\n;; bad\n(defn foo [x]\n  \"docstring\"\n  (bar x))\n----\n\n[NOTE]\n====\nPlace docstrings for `defprotocol` methods _after_ the argument vector:\n\n[source,clojure]\n----\n(defprotocol MyProtocol\n  \"MyProtocol docstring\"\n  (foo [this x y z]\n    \"foo docstring\")\n  (bar [this]\n    \"bar docstring\"))\n----\n====\n\n== Testing\n\n=== Test Directory Structure [[test-directory-structure]]\n\nStore your tests in a separate directory, typically `test/yourproject/` (as\nopposed to `src/yourproject/`). Your build tool is responsible for making\nthem available in the contexts where they are necessary; most templates\nwill do this for you automatically.\n\n=== Test Namespace Naming [[test-ns-naming]]\n\nName your ns `yourproject.something-test`, a file which usually lives in\n`test/yourproject/something_test.clj` (or `.cljc`, `cljs`).\n\n=== Test Naming [[test-naming]]\n\nWhen using `clojure.test`, define your tests\nwith `deftest` and name them `something-test`.\n\n[source,clojure]\n----\n;; good\n(deftest something-test ...)\n\n;; bad\n(deftest something-tests ...)\n(deftest test-something ...)\n(deftest something ...)\n----\n\n== Library Organization\n\n=== Library Coordinates [[lib-coordinates]]\n\nIf you are publishing libraries to be used by others, make sure to\nfollow the https://central.sonatype.org/pages/choosing-your-coordinates.html[Central Repository\nguidelines]\nfor choosing your `groupId` and `artifactId`. This helps to prevent\nname conflicts and facilitates the widest possible use. A good\nexample is https://github.com/stuartsierra/component[Component] - its\ncoordinates are `com.stuartsierra/component`.\n\nAnother approach that's popular in the wild is to use a project (or organization)\nname as the `groupId` instead of domain name. Examples of such naming would be:\n\n* `cider/cider-nrepl`\n* `nrepl/nrepl`\n* `nrepl/drawbridge`\n* `clj-commons/fs`\n\n=== Minimize Dependencies [[lib-min-dependencies]]\n\nAvoid unnecessary dependencies. For example, a three-line utility\nfunction copied into a project is usually better than a dependency\nthat drags in hundreds of vars you do not plan to use.\n\n=== Tool-agnostic [[lib-core-separate-from-tools]]\n\nDeliver core functionality and integration points in separate\nartifacts.  That way, consumers can consume your library without\nbeing constrained by your unrelated tooling preferences. For example,\nhttps://github.com/stuartsierra/component[Component] provides\ncore functionality, and\nhttps://github.com/stuartsierra/reloaded[reloaded] provides leiningen\nintegration.\n\n== Existential\n\n=== Be Functional [[be-functional]]\n\nCode in a functional way, using mutation only when it makes sense.\n\n=== Be Consistent [[be-consistent]]\n\nBe consistent. In an ideal world, be consistent with these guidelines.\n\n=== Common Sense [[common-sense]]\n\nUse common sense.\n\n== Tools\n\nOne problem with style guides is that it's often hard to remember all the guidelines\nand to apply them consistently. We're only humans, after all. Fortunately,\nthere are a bunch of tools that can do most of the work for us.\n\nTIP: It's a great idea run such tools as part of your continuous integration (CI).\nThis ensure that all the code in one project is consistent with the style you're\naiming for.\n\n=== Lint Tools\n\nThere are some lint tools created by the Clojure community that might aid you\nin your endeavor to write idiomatic Clojure code.\n\n* https://github.com/jonase/kibit[kibit] is a static code analyzer for\nClojure which uses https://github.com/clojure/core.logic[core.logic] to\nsearch for patterns of code for which there might exist a more idiomatic\nfunction or macro.\n* https://github.com/borkdude/clj-kondo[clj-kondo] is a linter that detects\na wide number of discouraged patterns and suggests improvements, based on this\nstyle guide.\n\n=== Code Formatters\n\nWhile most Clojure editors and IDEs can format the code, according to the layout guidelines\noutlined here, it's always handy to have some command-line code formatting tools. There are\na couple of options for Clojure that do a great job when it comes to formatting the code\nas suggested in this guide:\n\n* https://github.com/weavejester/cljfmt[cljfmt]\n* https://github.com/greglook/cljstyle[cljstyle]\n* https://github.com/kkinnear/zprint[zprint] (the documentation for configuring it to use the community formatting rules is https://github.com/kkinnear/zprint/blob/master/doc/options/community.md[here])\n\nNOTE: When it comes to editors - Emacs's `clojure-mode` by default will format the code exactly as outlined in the guide.\nOther editors might require some configuration tweaking to produce the same results.\n\n== History\n\nThis guide was started in 2013 by https://github.com/bbatsov[Bozhidar Batsov], following the\nsuccess of a https://rubystyle.guide/[similar project] he had created in the Ruby community.\n\nBozhidar was very passionate about both Clojure and good programming style and he wanted to bridge the gap between what was\ncovered by the https://clojure.org/community/contrib_howto#_coding_guidelines[Clojure library coding guidelines] and what the style guides for languages like Java, Python and Ruby would typically cover.\nBozhidar still serves as the guide's primary editor, but there's an entire editor team supporting the project.\n\nSince the inception of the guide we've received a lot of feedback from members of the exceptional Clojure community around the world.\nThanks for all the suggestions and the support! Together we can make a resource beneficial to each and every Clojure developer out there.\n\n== Sources of Inspiration\n\nMany people, books, presentations, articles and other style guides influenced the community Clojure style guide. Here are some of them:\n\n* https://en.wikipedia.org/wiki/The_Elements_of_Style[\"The Elements of Style\"]\n* https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style[\"The Elements of Programming Style\"]\n* https://www.python.org/dev/peps/pep-0008/[Python Style Guide (PEP-8)]\n* https://rubystyle.guide/[Community Ruby Style Guide]\n* https://google.github.io/styleguide/lispguide.xml[Google's Common Lisp Style Guide]\n* http://community.schemewiki.org/?scheme-style[scheme-style]\n* https://clojure.org/community/contrib_howto#_coding_guidelines[Clojure Library Coding Guidelines]\n* http://www.clojurebook.com/[\"Clojure Programming\"]\n* https://www.manning.com/books/the-joy-of-clojure-second-edition[\"The Joy of Clojure\"]\n* https://elementsofclojure.com/[\"Elements of Clojure\"]\n* https://pragprog.com/titles/vmclojeco/clojure-applied/[\"Clojure Applied\"]\n* https://stuartsierra.com/tag/dos-and-donts[Stuart Sierra's \"Clojure Dos and Don't\" blog series]\n\n== Editor Team\n\nThe Clojure style guide is stewarded by an editor team of experienced\nClojurists that aims to reduce all the input we get (e.g. feedback and\nsuggestions) to a better reference for everyone.\n\n* https://metaredux.com/about/[Bozhidar Batsov]\n* https://insideclojure.org/about/[Alex Miller]\n* https://danielcompton.net/about[Daniel Compton]\n* https://corfield.org/[Sean Corfield]\n\n== Contributing\n\nThe guide is still a work in progress - some guidelines are lacking examples, some guidelines don't have examples that illustrate them clearly enough.\nImproving such guidelines is a great (and simple way) to help the Clojure community!\n\nIn due time these issues will (hopefully) be addressed - just keep them in mind for now.\n\nNothing written in this guide is set in stone.\nIt's my desire to work together with everyone interested in Clojure coding style, so that we could ultimately create a resource that will be beneficial to the entire Clojure community.\n\nFeel free to open tickets or send pull requests with improvements.\nThanks in advance for your help!\n\nYou can also support the style guide (and all my Clojure projects like\nCIDER, nREPL, orchard, etc) with financial contributions via one of the following platforms:\n\n* https://github.com/sponsors/bbatsov[GitHub Sponsors]\n* https://ko-fi.com/bbatsov[ko-fi]\n* https://www.patreon.com/bbatsov[Patreon]\n* https://www.paypal.me/bbatsov[PayPal]\n\n=== How to Contribute?\n\nIt's easy, just follow the contribution guidelines below:\n\n* https://help.github.com/articles/fork-a-repo[Fork] https://github.com/bbatsov/clojure-style-guide[bbatsov/clojure-style-guide] on GitHub\n* Make your feature addition or bug fix in a feature branch.\n* Include a http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[good description] of your changes\n* Push your feature branch to GitHub\n* Send a https://help.github.com/articles/using-pull-requests[Pull Request]\n\n== Colophon\n\nThis guide is written in https://asciidoc.org/[AsciiDoc] and is published as HTML using https://asciidoctor.org/[AsciiDoctor].\nThe HTML version of the guide is hosted on GitHub Pages.\n\nOriginally the guide was written in Markdown, but was converted to AsciiDoc in 2019.\n\n== License\n\nimage:https://i.creativecommons.org/l/by/3.0/88x31.png[Creative Commons License]\nThis work is licensed under a\nhttps://creativecommons.org/licenses/by/3.0/deed.en_US[Creative Commons Attribution 3.0 Unported License]\n\n== Spread the Word\n\nA community-driven style guide is of little use to a community that\ndoesn't know about its existence. Tweet about the guide, share it with\nyour friends and colleagues. Every comment, suggestion or opinion we\nget makes the guide just a little bit better. And we want to have the\nbest possible guide, don't we?\n","funding_links":["https://github.com/sponsors/bbatsov","https://ko-fi.com/bbatsov","https://www.patreon.com/bbatsov","https://www.paypal.me/bbatsov"],"categories":["Programming Languages","Clojure","Others","info","计算机编程 数据结构与算法","Unknown","Guides"],"sub_categories":["Clojure","网络服务_其他"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbbatsov%2Fclojure-style-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbbatsov%2Fclojure-style-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbbatsov%2Fclojure-style-guide/lists"}