Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Check for round-about clojure.string/reverse.
; bad
(apply str x)
; good
(clojure.string/join x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Check for round-about clojure.string/join
.
; bad
(apply str (interpose "," x))
; good
(clojure.string/join "," x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Check for round-about clojure.string/reverse
.
; bad
(apply str (reverse x))
; good
(clojure.string/reverse x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Layering assoc
calls are hard to read. assoc-in
is known and idiomatic.
; bad
(assoc coll :key1 (assoc (:key2 coll) :key2 new-val))
(assoc coll :key1 (assoc (coll :key2) :key2 new-val))
(assoc coll :key1 (assoc (get coll :key2) :key2 new-val))
; good
(assoc-in coll [:key1 :key2] new-val)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 0.1.85 |
It's nice when the default branch is consistent.
; bad
(cond
(< 10 num) (println 10)
(< 5 num) (println 5)
true (println 0))
; good
(cond
(< 10 num) (println 10)
(< 5 num) (println 5)
:else (println 0))
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
vector
is succinct and meaningful.
; bad
(conj [] :a b {:c 1})
; good
(vector :a b {:c 1})
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 1.0 | 1.0 |
(defn [])
is preferable over (def (fn []))
. Extrapolate to closures.
# bad
(def check-inclusion
(let [allowed #{:a :b :c}]
(fn [i] (contains? allowed i))))
# good
(let [allowed #{:a :b :c}]
(defn check-inclusion [i]
(contains? allowed i)))
# bad
(def some-func
(fn [i] (+ i 100)))
# good
(defn some-func [i]
(+ i 100))
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
false?
exists so use it.
; bad
(= false x)
(= x false)
; good
(false? x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
nil?
exists so use it.
; bad
(= nil x)
(= x nil)
; good
(nil? x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
true?
exists so use it.
; bad
(= true x)
(= x true)
; good
(true? x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
zero?
exists so use it.
; bad
(= 0 num)
(= num 0)
(== 0 num)
(== num 0)
; good
(zero? num)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Check for (filter (complement pred) coll)
.
; bad
(filter (complement even?) coll)
; good
(remove even? coll)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
filterv is preferable for using transients.
; bad
(vec (filter pred coll))
; good
(filterv pred coll)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
ffirst is succinct and meaningful.
; bad
(first (first coll))
; good
(ffirst coll)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
fnext
is succinct and meaningful.
; bad
(first (next coll))
; good
(fnext coll)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
let
has an implicit do
, so use it.
; bad
(let [a 1 b 2] (do (println a) (println b)))
; good
(let [a 1 b 2] (println a) (println b))
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Check for (apply concat (apply map x y))
.
; bad
(apply concat (apply map x y))
; good
(mapcat x y)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Check for (apply concat (map x y z))
.
; bad
(apply concat (map x y))
(apply concat (map x y z))
; good
(mapcat x y)
(mapcat x y z)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Checks for simple -1 that should use clojure.core/dec
.
; bad
(- x 1)
; good
(dec x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Checks for x - 0.
; bad
(- x 0)
; good
x
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 1.3.0 | 1.3.0 |
Sort the arities of a function from fewest to most arguments.
# bad
(defn foo
([x] (foo x 1))
([x y & more] (reduce foo (+ x y) more))
([x y] (+ x y)))
# good
(defn foo
([x] (foo x 1))
([x y] (+ x y))
([x y & more] (reduce foo (+ x y) more)))
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Checks for (* x 1).
; bad
(* x 1)
(* 1 x)
; good
x
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Checks for (* x 0).
; bad
(* x 0)
(* 0 x)
; good
0
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
neg?
exists so use it.
; bad
(< num 0)
(> 0 num)
; good
(neg? num)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Checks for simple nested additions.
; bad
(+ x (+ y z))
(+ x (+ y z a))
; good
(+ x y z)
(+ x y z a)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Checks for simple nested multiply.
; bad
(* x (* y z))
(* x (* y z a))
; good
(* x y z)
(* x y z a)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.69 | 0.1.69 |
new
is discouraged for dot usage.
; bad
(new java.util.ArrayList 100)
; good
(java.util.ArrayList. 100)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
nfirst is succinct and meaningful.
; bad
(next (first coll))
; good
(nfirst coll)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
nnext is succinct and meaningful.
; bad
(next (next coll))
; good
(nnext coll)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
not=
exists, so use it.
; bad
(not (= num1 num2))
; good
(not= num1 num2)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
some?
exists so use it.
; bad
(not (nil? x))
; good
(some? x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
not-any? is succinct and meaningful.
; bad
(not (some even? coll))
; good
(not-any? even? coll)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Checks for simple +1 that should use clojure.core/inc
.
; bad
(+ x 1)
(+ 1 x)
; good
(inc x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Checks for x + 0.
; bad
(+ x 0)
(+ 0 x)
; good
x
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
pos?
exists so use it.
; bad
(< 0 num)
(> num 0)
; good
(pos? num)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.69 | 0.1.69 |
Use boolean
if you must return true
or false
from an expression.
# bad
(if some-val true false)
(if (some-func) true false)
# good
(boolean some-val)
(boolean (some-func))
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.69 | 0.1.69 |
NOTE: Requires Clojure version 1.11.0.
Prefer clojure.math to interop.
# bad
Math/PI
(Math/atan 45)
# good
clojure.math/PI
(clojure.math/atan 45)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 1.9.0 | 1.9.0 |
Prefer clojure.math to interop.
# bad
(.toUpperCase "hello world")
# good
(clojure.string/upper-case "hello world")
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.69 | 1.0 |
cond
checking against the same value in every branch is a code smell.
This rule uses the first test-expr as the template to compare against each other test-expr. It has a number of conditions it checks as it runs:
cond
is well-formed (aka even number of args).cond
has more than 1 pair.true
or a keyword.Provided all of that is true, then the middle arguments of the test-exprs are
gathered and rendered into a condp
.
# bad
(cond
(= 1 x) :one
(= 2 x) :two
(= 3 x) :three
(= 4 x) :four)
# good
(condp = x
1 :one
2 :two
3 :three
4 :four)
# bad
(cond
(= 1 x) :one
(= 2 x) :two
(= 3 x) :three
:else :big)
# good
(condp = x
1 :one
2 :two
3 :three
:big)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 0.1.69 |
vary-meta
works like swap!
, so no need to access and overwrite in two steps.
; bad
(with-meta x (assoc (meta x) :filename filename))
; good
(vary-meta x assoc :filename filename)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.69 | 0.1.69 |
Directly nested lets can be merged into a single let block.
# bad
(let [a 1]
(let [b 2]
(println a b)))
(let [a 1
b 2]
(println a b))
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 1.10.0 | 1.10.0 |
Clojure regex literals (#"") are passed to java.util.regex.Pattern/compile
at read time. re-pattern
checks if the given arg is a Pattern, making it a no-op when given a regex literal.
# bad
(re-pattern #".*")
# good
#".*"
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.119 | 1.0 |
Sets can be used as functions and they're converted to static items when they contain constants, making them fairly fast. However, they're not as fast as [[case]] and their meaning is less clear at first glance.
# bad
(#{'a 'b 'c} elem)
# good
(case elem (a b c) elem nil)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.69 | 0.1.69 |
assoc-in
loops over the args, calling assoc
for each key. If given a single key,
just call assoc
directly instead for performance and readability improvements.
; bad
(assoc-in coll [:k] 10)
; good
(assoc coll :k 10)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Convert (.toString)
to (str)
.
; bad
(.toString x)
; good
(str x)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
update-in
-ing an assoc
with the same key are hard to read. assoc-in
is known
and idiomatic.
; bad
(update-in coll [:a :b] assoc 5)
; good
(assoc-in coll [:a :b] 5)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.69 | 1.2.0 |
A single item in a do
is a no-op. However, it is sometimes necessary to wrap expressions in do
s to avoid issues, so do
surrounding ~@something
will be skipped as well as #(do something)
.
; bad
(do coll)
; good
coll
; skipped
(do ~@body)
#(do [%1 %2])
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1.69 | 1.2.0 |
when
already defines an implicit do
. Rely on it.
; bad
(when x (do (println :a) (println :b) :c))
; good
(when x (println :a) (println :b) :c)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
when-not
exists so use it lol.
; bad
(when (not x) :a :b :c)
; good
(when-not x :a :b :c)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
when-not
already defines an implicit do
. Rely on it.
; bad
(when-not x (do (println :a) (println :b) :c))
; good
(when-not x (println :a) (println :b) :c)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 0.1.69 |
seq
returns nil
when given an empty collection. empty?
is implemented as
(not (seq coll))
so it's best and fastest to use seq
directly.
; bad
(when-not (empty? ?x) &&. ?y)
; good
(when (seq ?x) &&. ?y)
Enabled by default | Version Added | Version Updated |
---|---|---|
true | 0.1 | 1.2.0 |
Two not
s cancel each other out.
; bad
(when-not (not x) y z)
; good
(when x y z)
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close