@@ -1947,11 +1947,24 @@ ____
19471947=== Avoid Lists [[avoid-lists]]
19481948
19491949Avoid the use of lists for generic data storage (unless a list is
1950- exactly what you need).
1950+ exactly what you need). Vectors provide O(1) indexed access, efficient
1951+ `conj` at the end, and work better with the rest of the standard
1952+ library.
1953+
1954+ [source,clojure]
1955+ ----
1956+ ;; good
1957+ [1 2 3]
1958+
1959+ ;; bad - a list used as a mere container
1960+ '(1 2 3)
1961+ ----
19511962
19521963=== Keywords For Hash Keys [[keywords-for-hash-keys]]
19531964
1954- Prefer the use of keywords for hash keys.
1965+ Prefer the use of keywords for hash keys. Keywords are interned (fast
1966+ equality checks), can be used as functions to look themselves up in a
1967+ map, and stand out visually from values.
19551968
19561969[source,clojure]
19571970----
@@ -1984,6 +1997,18 @@ when the values are compile-time constants.
19841997=== Avoid Index Based Collection Access [[avoid-index-based-coll-access]]
19851998
19861999Avoid accessing collection members by index whenever possible.
2000+ Destructuring and sequence functions convey intent more clearly and
2001+ don't break when the collection order changes.
2002+
2003+ [source,clojure]
2004+ ----
2005+ ;; good - destructuring makes the meaning clear
2006+ (let [[x y] point]
2007+ (process x y))
2008+
2009+ ;; bad - fragile and says nothing about what's at index 0 and 1
2010+ (process (nth point 0) (nth point 1))
2011+ ----
19872012
19882013=== Keywords as Functions for Map Values Retrieval [[keywords-as-fn-to-get-map-values]]
19892014
@@ -2028,16 +2053,51 @@ Leverage the fact that keywords can be used as functions of a collection.
20282053=== Avoid Transient Collections [[avoid-transient-colls]]
20292054
20302055Avoid the use of transient collections, except for
2031- performance-critical portions of the code.
2056+ performance-critical portions of the code. Transients add complexity
2057+ (they must not be shared across threads and require a different set of
2058+ mutation functions) while persistent collections are already quite fast
2059+ for most use cases.
2060+
2061+ [source,clojure]
2062+ ----
2063+ ;; good - persistent collections are fine for everyday code
2064+ (reduce conj [] (range 1000))
2065+
2066+ ;; ok in a hot path where benchmarks justify it
2067+ (persistent! (reduce conj! (transient []) (range 1000)))
2068+ ----
20322069
20332070=== Avoid Java Collections [[avoid-java-colls]]
20342071
2035- Avoid the use of Java collections.
2072+ Avoid the use of Java collections. Java collections are mutable and do
2073+ not implement Clojure's sequence abstractions, making them incompatible
2074+ with the standard library.
2075+
2076+ [source,clojure]
2077+ ----
2078+ ;; good
2079+ {:name "Bruce" :age 30}
2080+
2081+ ;; bad
2082+ (doto (java.util.HashMap.)
2083+ (.put :name "Bruce")
2084+ (.put :age 30))
2085+ ----
20362086
20372087=== Avoid Java Arrays [[avoid-java-arrays]]
20382088
20392089Avoid the use of Java arrays, except for interop scenarios and
2040- performance-critical code dealing heavily with primitive types.
2090+ performance-critical code dealing heavily with primitive types. Arrays
2091+ are mutable, have no literal syntax, and don't print readably.
2092+
2093+ [source,clojure]
2094+ ----
2095+ ;; good
2096+ [1 2 3]
2097+
2098+ ;; bad - unless required for interop or primitive performance
2099+ (int-array [1 2 3])
2100+ ----
20412101
20422102== Types & Records
20432103
0 commit comments