Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Clojure Linters
Search
Kent OHASHI
February 15, 2018
Programming
0
19
Clojure Linters
Utilise linters for clean Clojure code (*> ᴗ •*)ゞ
Kent OHASHI
February 15, 2018
Tweet
Share
More Decks by Kent OHASHI
See All by Kent OHASHI
TDD with RDD: Changed Developer Experience through Clojure/Lisp REPLs
lagenorhynque
0
22
My Favourite Book in 2024: Get Rid of Your Japanese Accent
lagenorhynque
0
40
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
lagenorhynque
0
28
Exploring Collections in JVM Languages through Internals of map Function
lagenorhynque
0
29
Kotlin Meets Data-Oriented Programming
lagenorhynque
0
32
Introduction to Tree Representations in RDB 2024
lagenorhynque
0
55
Boundary between Mutability and Immutability
lagenorhynque
0
62
Learning Modern Web API Styles from IDL: REST, GraphQL, gRPC
lagenorhynque
0
97
Team Geek Revisited
lagenorhynque
0
79
Other Decks in Programming
See All in Programming
Multi Step Form, Decentralized Autonomous Organization
pumpkiinbell
1
810
Flutter × Firebase Genkit で加速する生成 AI アプリ開発
coborinai
0
160
Go 1.24でジェネリックになった型エイリアスの紹介
syumai
1
190
2024年のWebフロントエンドのふりかえりと2025年
sakito
3
260
XStateを用いた堅牢なReact Components設計~複雑なClient Stateをシンプルに~ @React Tokyo ミートアップ #2
kfurusho
1
950
さいきょうのレイヤードアーキテクチャについて考えてみた
yahiru
3
760
CSS Linter による Baseline サポートの仕組み
ryo_manba
1
140
Conform を推す - Advocating for Conform
mizoguchicoji
3
700
お前もAI鬼にならないか?👹Bolt & Cursor & Supabase & Vercelで人間をやめるぞ、ジョジョー!👺
taishiyade
7
4.1k
なぜイベント駆動が必要なのか - CQRS/ESで解く複雑系システムの課題 -
j5ik2o
12
4.4k
富山発の個人開発サービスで日本中の学校の業務を改善した話
krpk1900
5
390
Grafana Cloudとソラカメ
devoc
0
180
Featured
See All Featured
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
Writing Fast Ruby
sferik
628
61k
Building Applications with DynamoDB
mza
93
6.2k
Making the Leap to Tech Lead
cromwellryan
133
9.1k
Why You Should Never Use an ORM
jnunemaker
PRO
55
9.2k
Testing 201, or: Great Expectations
jmmastey
42
7.2k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.4k
Raft: Consensus for Rubyists
vanstee
137
6.8k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
114
50k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
21
2.5k
Transcript
Clojure Linters
Self-introduction /laʒenɔʁɛ̃k/ カマイルカ lagénorhynque (defprofile lagénorhynque :name "Kent OHASHI" :languages
[Clojure Haskell Python Scala English français Deutsch русский] :interests [programming language-learning mathematics] :contributing [github.com/japan-clojurians/clojure-site-ja])
「Clojureをプロダクトに導⼊した話」
1. cljfmt: formatter 2. eastwood: linter 3. kibit: idiom checker
4. Example Usage 5. Other Tools
formatter cljfmt
What's the problem? (when something (something-else) )
$ lein cljfmt check (when something - (something-else) -) +
(something-else))
What's the problem? (when something something-else)
$ lein cljfmt check (when something - something-else) + something-else)
What's the problem? (filter even? (range 1 10))
$ lein cljfmt check (filter even? - (range 1 10))
+ (range 1 10))
What's the problem? (if something ala bala)
$ lein cljfmt check (if something - ala - bala)
+ ala + bala)
What's the problem? (or ala bala portokala)
$ lein cljfmt check (or - ala - bala -
portokala) + ala + bala + portokala)
linter eastwood
What's the problem? (ns linting-example.eastwood-target (:use [clojure.string]))
$ lein eastwood src/linting_example/eastwood_target.clj:2:10: unlimited-use: Unl imited use of ([clojure.string])
in linting-example.eastwood-tar get
What's the problem? (if-let [x []] (conj x 42) :falsy)
$ lein eastwood src/linting_example/eastwood_target.clj:4:1: constant-test: Test expression is always logical
true or always logical false: [] in form (if temp__5455__auto__ (clojure.core/let [x temp__5455__aut o__] (conj x 42)) :falsy)
What's the problem? (defn f [x] (def y (* x
x)) (+ y 2))
$ lein eastwood src/linting_example/eastwood_target.clj:9:8: def-in-def: There i s a def
of y nested inside def f
What's the problem? (defn g [x] "blah blah blah." (*
x x))
$ lein eastwood src/linting_example/eastwood_target.clj:12:7: misplaced-docstrin gs: Possibly misplaced docstring, g
src/linting_example/eastwood_target.clj:12:1: unused-ret-vals: C onstant value is discarded: "blah blah blah."
What's the problem? (defn h [str] (str "Hello, " str
"!"))
$ lein eastwood src/linting_example/eastwood_target.clj:17:3: local-shadows-var: local: str invoked as function
shadows var: #'clojure.core/str
idiom checker kibit
What's the problem? (defn add-one [x] (+ x 1))
$ lein kibit At src/linting_example/kibit_target.clj:4: Consider using: (inc x) instead
of: (+ x 1)
What's the problem? (defn check-if-zero? [x] (== x 0))
$ lein kibit At src/linting_example/kibit_target.clj:7: Consider using: (zero? x) instead
of: (== x 0)
What's the problem? (defn zip-with-* [xs ys] (map #(* %1
%2) xs ys))
$ lein kibit At src/linting_example/kibit_target.clj:null: Consider using: * instead of:
#(* %1 %2)
What's the problem? (defn coll->vec [coll] (into [] coll))
$ lein kibit At src/linting_example/kibit_target.clj:13: Consider using: (vec coll) instead
of: (into [] coll)
What's the problem? (defn flat-map [f coll] (apply concat (map
f coll)))
$ lein kibit At src/linting_example/kibit_target.clj:16: Consider using: (mapcat f coll)
instead of: (apply concat (map f coll))
Example Usage
e.g. ↓↓↓ lagenorhynque/situated-program- challenge/rest-server/project.clj :plugins [[jonase/eastwood "0.2.5"] [lein-cljfmt "0.5.7"] [lein-kibit
"0.1.6"]] :aliases {"lint" ^{:doc "Execute cljfmt check, eastwood and kibit."} ["do" ["cljfmt" "check"] ["eastwood" "{:source-paths [\"src\"]}"] ["kibit"]]} lein cljfmt check && lein eastwood <opts> && lein kibit = lein do cljfmt check, eastwood <opts>, kibit = lein lint # alias as `lint`
$ lein lint All source files formatted correctly == Eastwood
0.2.5 Clojure 1.9.0 JVM 9.0.1 Directories scanned for source files: src test == Linting rest-server.util == == Linting rest-server.boundary.db.core == == Linting rest-server.boundary.db.group == ... == Linting rest-server.handler.venue-test == == Linting rest-server.handler.meetup-test == == Linting rest-server.handler.member-test == == Warnings: 0 (not including reflection warnings) Exceptions thrown: 0
Other Tools
dependency lein deps :tree lein-ancient
namespace slamhound
dead code Yagni
vulnerability lein-nvd
test coverage cloverage
misc. lein-bikeshed
Utilise linters for clean Clojure code!
Further Reading Clojure Code Quality Tools My Clojure Toolchain: Leiningen
Automating Style In Clojure The state of code quality tools in Clojure clojure-style-guide