Practical REPL-driven	Development with	Clojure
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])
Contents 1. Clojure	Quick	Intro 2. Leiningen 3. Clojure	REPL 4. Lisp	Editing 5. REPL-driven	Development	in	Practice
Clojure	Quick	Intro
Clojure Lisp S-expressions,	macros,	etc. REPL-driven	development functional	programming	language dynamic	language JVM	language	(cf.	ClojureScript) ⇒	simple	and	powerful	language
literals type example string "abc" character a number 1,	2.0,	3N,	4.5M,	6/7,	8r10 boolean true,	false nil nil keyword :a,	:user/a,	::a,	::x/a symbol 'a,	'user/a,	`a,	`x/a
type example list '(1 2 3),	'(+ 1 2 3) vector [1 2 3] set #{1 2 3} map {:a 1 :b 2},	#:user{:a 1 :b 2}, #::{:a 1 :b 2},	#::x{:a 1 :b 2} function (fn [x] (* x x))
the	syntax operator function macro special	form (op arg1 arg2 ... argn)
Leiningen
lein repl starts	Clojure	REPL $ lein repl nREPL server started on port 49482 on host 127.0.0.1 - nrepl://1 27.0.0.1:49482 REPL-y 0.3.7, nREPL 0.2.12 Clojure 1.8.0 Java HotSpot(TM) 64-Bit Server VM 1.8.0_121-b13 Docs: (doc function-name-here) (find-doc "part-of-name-here") Source: (source function-name-here) Javadoc: (javadoc java-object-or-class-here) Exit: Control+D or (exit) or (quit) Results: Stored in vars *1, *2, *3, an exception in *e user=>
lein new generates	a	new	Clojure	project generate	a	project	with	app	template cf. $ lein new app clj-demo Generating a project called clj-demo based on the 'app' template lein-template
$ tree clj-demo/ clj-demo/ ├── CHANGELOG.md ├── LICENSE ├── README.md ├── doc │ └── intro.md ├── project.clj ├── resources ├── src │ └── clj_demo │ └── core.clj └── test └── clj_demo └── core_test.clj
lein run runs	-main	function $ cd clj-demo/ $ lein run Hello, World!
cf.	src/clj_demo/core.clj (ns clj-demo.core (:gen-class)) (defn -main "I don't do a whole lot ... yet." [& args] (println "Hello, World!"))
lein test runs	tests $ lein test lein test clj-demo.core-test lein test :only clj-demo.core-test/a-test FAIL in (a-test) (core_test.clj:7) FIXME, I fail. expected: (= 0 1) actual: (not (= 0 1)) Ran 1 tests containing 1 assertions. 1 failures, 0 errors. Tests failed.
cf.	test/clj_demo/core_test.clj (ns clj-demo.core-test (:require [clojure.test :refer :all] [clj-demo.core :refer :all])) (deftest a-test (testing "FIXME, I fail." (is (= 0 1))))
lein uberjar creates	jar	files $ lein uberjar Compiling clj-demo.core Created /Users/k.ohashi/code/clj-demo/target/uberjar/clj-demo-0. 1.0-SNAPSHOT.jar Created /Users/k.ohashi/code/clj-demo/target/uberjar/clj-demo-0. 1.0-SNAPSHOT-standalone.jar $ java -jar target/uberjar/clj-demo-0.1.0-SNAPSHOT-standalone.ja r Hello, World!
Clojure	REPL
evaluate	expressions clj-demo.core=> (map inc [0 1 2]) (1 2 3) clj-demo.core=> (println (map inc [0 1 2])) (1 2 3) nil
clojure.repl/doc prints	documentation clj-demo.core=> (doc map) ------------------------- clojure.core/map ([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]) Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments. Returns a transducer when no collection is provided. nil
clojure.repl/source prints	source	code clj-demo.core=> (source map) (defn map "Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments. Returns a transducer when no collection is provided." {:added "1.0" :static true} ([f] (fn [rf] (fn ([] (rf)) ([result] (rf result)) ([result input] (rf result (f input))) ([result input & inputs] (rf result (apply f input inputs))))))
clojure.core/*1,	*2,	*3 special	vars	bound	to	the	most	recent	values printed clj-demo.core=> 21 21 clj-demo.core=> 2 2 clj-demo.core=> (* *2 *1) 42
clojure.core/*e special	var	bound	to	the	most	recent	exception caught	by	the	REPL clj-demo.core=> (+ 1 "2") ClassCastException java.lang.String cannot be cast to java.lang.Number clj-demo.core=> *e #error { :cause "java.lang.String cannot be cast to java.lang.Number" :via [{:type java.lang.ClassCastException :message "java.lang.String cannot be cast to java.lang.Number" :at [clojure.lang.Numbers add "Numbers.java" 128]}] :trace [[clojure.lang.Numbers add "Numbers.java" 128] [clojure.lang.Numbers add "Numbers.java" 3640] [clj_demo.core$eval1328 invokeStatic "form-init3161334546666357405.cl [clj_demo.core$eval1328 invoke "form-init3161334546666357405.clj" 1] [clojure.lang.Compiler eval "Compiler.java" 6927] [clojure.lang.Compiler eval "Compiler.java" 6890] [clojure.core$eval invokeStatic "core.clj" 3105]
search	documentation clojure.repl/find-doc clojure.repl/apropos clojure.java.javadoc/javadoc
Lisp	editing
Lisp	editing	plugins Parinfer ParEdit
Parinfer automatically	adjust	parentheses	when	editing indentation	(Indent	mode),	indentation	when editing	parentheses	(Paren	mode)
e.g.	Atom	with	Parinfer
(
defn␣my-map␣ [ f␣coll
⌘-<RET> <TAB>
(
when-let␣ [ s␣ ( seq␣coll
⌘-<RET> <TAB>
(
cons␣ ( f␣ ( first␣s
⌘-<RET> <TAB> <TAB>
(
my-map␣f␣ ( rest␣s
<up> <up> ⌘-<left>
(
lazy-seq <RET>
<down> <TAB> <down> <TAB>
ParEdit semi-automatically	adjust	parentheses	and indentation cf.	Smartparens
e.g.	Emacs	with	ParEdit
(
defn␣my-map␣ [ f␣coll
)
<RET>
(
when-let␣ [ s␣ ( seq␣coll
) )
<RET> (
cons␣ ( f␣ ( first␣s
) )
<RET>
( my-map␣f␣ ( rest␣s
<C>-<M>-u <C>-<M>-u <C>-<M>-u <C>-<M>-u
<M>-(
lazy-seq <RET>
REPL-driven	Development in	Practice
Course	A: Course	B: Clojure	Koans 4Clojure
Clojure	Koans cf.	ClojureScript	Koans
Clone	the	repository $ git clone git://github.com/functional-koans/clojure-koans.git Cloning into 'clojure-koans'... remote: Counting objects: 1590, done. remote: Compressing objects: 100% (7/7), done. remote: Total 1590 (delta 2), reused 4 (delta 1), pack-reused 15 80 Receiving objects: 100% (1590/1590), 269.87 KiB | 651.00 KiB/s, done. Resolving deltas: 100% (755/755), done.
Run	koans $ cd clojure-koans/ $ lein koan run Starting auto-runner... Considering /Users/k.ohashi/code/clojure-koans/src/koans/01_equa lities.clj... Now meditate upon /Users/k.ohashi/code/clojure-koans/src/koans/0 1_equalities.clj --------------------- Assertion failed! clojure.lang.ExceptionInfo: We shall contemplate truth by testin g reality, via equality (= __ true) {:line 6}, compiling:(/Users/k.ohashi/code/clojure-k oans/src/koans/01_equalities.clj:4:1)
Open	a	source le	with	your	favourite	editor $ emacs src/koans/01_equalities.clj
Start	Clojure	REPL
Evaluate	S-expressions
Send	S-expressions	to	REPL
Save	changes	and	check	the	meditation	result ... Now meditate upon /Users/k.ohashi/code/clojure-koans/src/koans/0 1_equalities.clj --------------------- Assertion failed! clojure.lang.ExceptionInfo: You can test equality of many things (= (+ 3 4) 7 (+ 2 __)) {:line 12}, compiling:(/Users/k.ohashi/co de/clojure-koans/src/koans/01_equalities.clj:4:1)
4Clojure
Open	a	new	buffer	with	your	favourite	editor $ emacs clj-demo/src/clj_demo/4clojure/problem22.clj
Start	Clojure	REPL
e.g. Count	a	Sequence Problem	#22 Write	a	function	which	returns	the total	number	of	elements	in	a sequence. (= (__ '(1 2 3 3 1)) 5) (= (__ "Hello World") 11) (= (__ [[1 2] [3 4] [5 6]]) 3) (= (__ '(13)) 1) (= (__ '(:a :b :c)) 3) Special	Restrictions:	count
Write	a	function
Evaluate	S-expressions
Send	S-expressions	to	REPL
Run	your	solution	on	the	problem	page (fn my-count [coll] (reduce (fn [n _] (inc n)) 0 coll))
Enjoy	REPL-driven development!
Further	Reading
Clojure	&	ClojureScript build	tool Clojure ClojureScript Leiningen
editor	plugins/settings Clojure	develompent Emacs cf. CIDER Clojure	初⼼者のための	Emacs	設定作りました 新:	Emacs	を使うモダンな	Clojure	開発環境 Spacemacs Clojure	layer Clojure	development	with	Spacemacs	& Cider
IntelliJ	IDEA Atom Cursive IntelliJ	IDEA	と	Cursive	で始める	—	Clojure	の⽇ 本語ガイド Atom	Clojure	Setup ClojureやりたいけどEmacsは厳しい⼈のための proto-repl⼊⾨
Vim Visual	Studio	Code Sublime	Text fireplace.vim clojureVSCode SublimeClojureSetup
Lisp	editing Parinfer ParEdit ParEdit	チュートリアル Paredit	Cheatsheet The	Animated	Guide	to	Paredit Lispってどう書くの?	-	Qiita Smartparens
REPL-driven	development Re:REPL-Driven	Development REPL	Driven	Development REPL	Driven	Development	and	Testing	in	Clojure

Practical REPL-driven Development with Clojure