Enabled | Added |
---|---|
true | 0.1 |
Check for round-about clojure.string/reverse.
; bad
(apply str x)
; good
(clojure.string/join x)
Enabled | Added |
---|---|
true | 0.1 |
Check for round-about str/join.
; bad
(apply str (interpose "," x))
; good
(clojure.string/join "," x)
Enabled | Added |
---|---|
true | 0.1 |
Check for round-about clojure.string/reverse.
; bad
(apply str (reverse x))
; good
(clojure.string/reverse x)
Enabled | Added |
---|---|
true | 0.1 |
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 | Added |
---|---|
true | 0.1 |
assoc
-ing an update with the same key are hard to read. update
is known and
idiomatic.
; bad
(assoc coll :a (+ (:a coll) 5))
(assoc coll :a (+ (coll :a) 5))
(assoc coll :a (+ (get coll :a) 5))
; good
(update coll :a + 5)
Enabled | Added |
---|---|
true | 0.1 |
A macro that nests an unquote-splicing
in a macro with a & body
can lead
to subtle hard to debug errors. Better to wrap the unquote-splicing
in
a do
to force it into 'expression position'.
# bad
`(binding [max mymax] ~@body)
# good
`(binding [max mymax] (let [res# (do ~@body)] res#))
Enabled | Added |
---|---|
true | 0.1 |
vector
is succinct and meaningful.
; bad
(conj [] :a b {:c 1})
; good
(vector :a b {:c 1})
Enabled | Added |
---|---|
true | 0.1 |
Checks for (/ x 1).
; bad
(/ x 1)
; good
x
Enabled | Added |
---|---|
true | 0.1 |
run!
uses reduce
which non-lazy.
; bad
(dorun (map println (range 10)))
; good
(run! println (range 10))
Enabled | Added |
---|---|
true | 0.1 |
Using the Obj/staticMethod
form maps the method call to Clojure's natural function
position.
; bad
(. Obj staticMethod args)
; good
(Obj/staticMethod args)
Enabled | Added |
---|---|
true | 0.1 |
Using the .method
form maps the method call to Clojure's natural function position.
; bad
(. obj method args)
; good
(.method obj args)
Enabled | Added |
---|---|
true | 0.1 |
deftype
and defrecord
will throw errors if you define multiple fields
with the same name, but it's good to catch these things early too.
# bad
(defrecord Foo [a b a])
# good
(defrecord Foo [a b c])
Enabled | Added |
---|---|
true | 0.1 |
false?
exists so use it.
; bad
(= false x)
(= x false)
; good
(false? x)
Enabled | Added |
---|---|
true | 0.1 |
nil?
exists so use it.
; bad
(= nil x)
(= x nil)
; good
(nil? x)
Enabled | Added |
---|---|
true | 0.1 |
true?
exists so use it.
; bad
(= true x)
(= x true)
; good
(true? x)
Enabled | Added |
---|---|
true | 0.1 |
zero?
exists so use it.
; bad
(= 0 num)
(= num 0)
(== 0 num)
(== num 0)
; good
(zero? num)
Enabled | Added |
---|---|
true | 0.1 |
Check for (filter (complement pred) coll)
; bad
(filter (complement even?) coll)
; good
(remove even? coll)
Enabled | Added |
---|---|
true | 0.1 |
filterv is preferable for using transients.
; bad
(vec (filter pred coll))
; good
(filterv pred coll)
Enabled | Added |
---|---|
true | 0.1 |
ffirst is succinct and meaningful.
; bad
(first (first coll))
; good
(ffirst coll)
Enabled | Added |
---|---|
true | 0.1 |
fnext is succinct and meaningful.
; bad
(first (next coll))
; good
(fnext coll)
Enabled | Added |
---|---|
true | 0.1 |
Avoid wrapping functions in pass-through anonymous function defitions.
; bad
(fn [num] (even? num))
; good
even?
; bad
(let [f (fn [num] (even? num))] ...)
; good
(let [f even?] ...)
Enabled | Added |
---|---|
true | 0.1 |
Idiomatic if
defines both branches. when
returns nil
in the else branch.
; bad
(if (some-func) :a nil)
; good
(when (some-func) :a)
Enabled | Added |
---|---|
true | 0.1 |
Idiomatic if-let
defines both branches. when-let
returns nil
in the else branch.
; bad
(if-let [a 1] a nil)
; good
(when-let [a 1] a)
Enabled | Added |
---|---|
true | 0.1 |
Idiomatic if
defines both branches. when-not
returns nil
in the truthy branch.
; bad
(if (some-func) nil :a)
; good
(when-not (some-func) :a)
Enabled | Added |
---|---|
true | 0.1 |
if-not
exists, so use it.
; bad
(if (not x) y z)
; good
(if-not x y z)
Enabled | Added |
---|---|
true | 0.1 |
when-not
already defines an implicit do
. Rely on it.
; bad
(if-not x (do (println :a) (println :b) :c))
; good
(if-not x (println :a) (println :b) :c)
Enabled | Added |
---|---|
true | 0.1 |
Two not
s cancel each other out.
; bad
(if-not (not x) y z)
; good
(if x y z)
Enabled | Added |
---|---|
true | 0.1 |
or
exists so use it lol.
; bad
(if x x y)
; good
(or x y)
Enabled | Added |
---|---|
true | 0.1 |
vec
and set
are succinct and meaningful.
; bad
(into [] coll)
; good
(vec coll)
; bad
(into #{} coll)
; good
(set coll)
Enabled | Added |
---|---|
true | 0.1 |
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 | Added |
---|---|
true | 0.1 |
if-let
exists so use it. Suggestions can be wrong as there's no code-walking to
determine if result
binding is used in falsy branch.
; bad
(let [result (some-func)] (if result (do-stuff result) (other-stuff)))
; good
(if-let [result (some-func)] (do-stuff result) (other-stuff))
Enabled | Added |
---|---|
true | 0.1 |
when-let
exists so use it.
; bad
(let [result (some-func)] (when result (do-stuff result)))
; good
(when-let [result (some-func)] (do-stuff result))
Enabled | Added |
---|---|
true | 0.1 |
loop
has an implicit do
. Use it.
; bad
(loop [] (do (println 1) (println 2)))
; good
(loop [] (println 1) (println 2))
Enabled | Added |
---|---|
true | 0.1 |
Empty loops with nested when can be while
.
; bad
(loop [] (when (some-func) (println 1) (println 2) (recur)))
; good
(while (some-func) (println 1) (println 2) (recur))
Enabled | Added |
---|---|
true | 0.1 |
Check for (apply concat (apply map x y))
; bad
(apply concat (apply map x y))
; good
(mapcat x y)
Enabled | Added |
---|---|
true | 0.1 |
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 | Added |
---|---|
true | 0.1 |
Checks for simple -1 that should use clojure.core/dec
.
; bad
(- x 1)
; good
(dec x)
Enabled | Added |
---|---|
true | 0.1 |
Checks for x - 0.
; bad
(- x 0)
; good
x
Enabled | Added |
---|---|
true | 0.1 |
when
calls should have at least 1 expression after the condition.
; bad
(when true)
(when (some-func))
; good
(when true (do-stuff))
(when (some-func) (do-stuff))
Enabled | Added |
---|---|
true | 0.1 |
Checks for (* x 1).
; bad
(* x 1)
(* 1 x)
; good
x
Enabled | Added |
---|---|
true | 0.1 |
Checks for (* x 0).
; bad
(* x 0)
(* 0 x)
; good
0
Enabled | Added |
---|---|
true | 0.1 |
neg?
exists so use it.
; bad
(< num 0)
(> 0 num)
; good
(neg? x)
Enabled | Added |
---|---|
true | 0.1 |
Checks for simple nested additions.
; bad
(+ x (+ y z))
(+ x (+ y z a))
; good
(+ x y z)
(+ x y z a)
Enabled | Added |
---|---|
true | 0.1 |
Checks for simple nested multiply.
; bad
(* x (* y z))
(* x (* y z a))
; good
(* x y z)
(* x y z a)
Enabled | Added |
---|---|
true | 0.1 |
nfirst is succinct and meaningful.
; bad
(next (first coll))
; good
(nfirst coll)
Enabled | Added |
---|---|
true | 0.1 |
nnext is succinct and meaningful.
; bad
(next (next coll))
; good
(nnext coll)
Enabled | Added |
---|---|
true | 0.1 |
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
(not (empty? coll))
; good
(seq coll)
Enabled | Added |
---|---|
true | 0.1 |
not=
exists, so use it.
; bad
(not (= num1 num2))
; good
(not= num1 num2)
Enabled | Added |
---|---|
true | 0.1 |
some?
exists so use it.
; bad
(not (nil? x))
; good
(some? x)
Enabled | Added |
---|---|
true | 0.1 |
not-any? is succinct and meaningful.
; bad
(not (some even? coll))
; good
(not-any? even? coll)
Enabled | Added |
---|---|
true | 0.1 |
Checks for simple +1 that should use clojure.core/inc
.
; bad
(+ x 1)
(+ 1 x)
; good
(inc x)
Enabled | Added |
---|---|
true | 0.1 |
Checks for x + 0.
; bad
(+ x 0)
(+ 0 x)
; good
x
Enabled | Added |
---|---|
true | 0.1 |
pos?
exists so use it.
; bad
(< 0 num)
(> num 0)
; good
(pos? x)
Enabled | Added |
---|---|
true | 0.1 |
A number of core functions take any number of arguments and return the arg if given only one. These calls are effectively no-ops, redundant, so they should be avoided.
Current list of clojure.core functions this linter checks:
->
, ->>
cond->
, cond->>
some->
, some->>
comp
, partial
, merge
; bad
(-> x)
(->> x)
(cond-> x)
(cond->> x)
(some-> x)
(some->> x)
(comp x)
(partial x)
(merge x)
; good
x
Enabled | Added |
---|---|
true | 0.1 |
repeatedly
has an arity for limiting the number of repeats with take
.
; bad
(take 5 (repeatedly (range 10))
; good
(repeatedly 5 (range 10))
Enabled | Added |
---|---|
true | 0.1 |
Threading macros require more effort to understand so only use them with multiple args to help with readability.
; bad
(-> x y)
(->> x y)
; good
(y x)
; bad
(-> x (y z))
; good
(y x z)
; bad
(->> x (y z))
; good
(y z x)
Enabled | Added |
---|---|
true | 0.1 |
Convert (.toString)
to (str)
.
; bad
(.toString x)
; good
(str x)
Enabled | Added |
---|---|
true | 0.1 |
A macro that wraps a splicing unquote in a try-catch or try-finally can lead
to subtle hard to debug errors. Better to wrap the splicing unquote in a do
to force it into 'expression position'.
# bad
`(try ~@body (finally :true))
# good
`(try (do ~@body) (finally :true))
Enabled | Added |
---|---|
true | 0.1 |
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 | Added |
---|---|
true | 0.1 |
A single item in a do
is a no-op.
; bad
(do coll)
; good
coll
Enabled | Added |
---|---|
true | 0.1 |
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 | Added |
---|---|
true | 0.1 |
when-not
exists so use it lol.
; bad
(when (not x) :a :b :c)
; good
(when-not x :a :b :c)
Enabled | Added |
---|---|
true | 0.1 |
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 | Added |
---|---|
true | 0.1 |
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 | Added |
---|---|
true | 0.1 |
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