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