Introduction to Clojure - Digital Digressions by Stuart … · Stuart Sierra Relevance, Inc....

Post on 31-Jul-2018

222 views 0 download

Transcript of Introduction to Clojure - Digital Digressions by Stuart … · Stuart Sierra Relevance, Inc....

Introduction toClojure

@stuartsierra#strangeloop

1Sunday, September 18, 2011

Bullet Points• The REPL

• Data and Code

• Working with Data

• Destructuring

• Higher-Order Functions

• Sequences

• Java Interop

• Libraries

• Namespaces

• Concurrency

• Macros

• Recursion

2Sunday, September 18, 2011

Stuart SierraRelevance, Inc.

Clojure/core

Clojure contributor

3Sunday, September 18, 2011

Where are you from?

• Lisp?

• Java / C# / C++

• ML / Haskell?

• Python / Ruby / Perl?

• Clojure?

• Multithreaded programming?

4Sunday, September 18, 2011

The REPL

5Sunday, September 18, 2011

The REPL

• READ

• EVALuate

• PRINT

• LOOP

6Sunday, September 18, 2011

The REPL

user=> (+ 1 2 3)6user=>

"you arehere"

type anexpression press

ENTER

result

7Sunday, September 18, 2011

The REPL

user=> (+ 1 2 3)6user=>

READ

EVAL

PRINT

LOOP

8Sunday, September 18, 2011

The REPL

user=> (println "Hello, World!")Hello, World!nil

expression withside effects

return valueprinted output

9Sunday, September 18, 2011

REPL Helpers: doc

user=> (doc when)-------------------------clojure.core/when([test & body])Macro Evaluates test. If logical true, evaluates body in an implicit do.nil

Fully-qualified name

Arguments

10Sunday, September 18, 2011

REPL Helpers: find-doc

user=> (find-doc "sequence")... all definitions with "sequence" in their documentation ...nil

11Sunday, September 18, 2011

REPL Helpers: apropos

user=> (apropos "map")(sorted-map ns-unmap zipmap map mapcat sorted-map-by map? amap struct-map proxy-mappings pmap map-indexed ns-map array-map hash-map)

12Sunday, September 18, 2011

user=> (source take)(defn take "Returns a lazy sequence of the first n items in coll, or all items if there are fewer than n." {:added "1.0" :static true} [n coll] (lazy-seq (when (pos? n) (when-let [s (seq coll)] (cons (first s) (take (dec n) (rest s)))))))nil

REPL Helpers: source

Source code ofthe 'take' function

13Sunday, September 18, 2011

Data and Code

14Sunday, September 18, 2011

Literals

example Java type

"hello" String

\e Character

42 Long

6.022e23 Double

1.0M BigDecimal

9223372036854775808N clojure.lang.BigInt

22/7 clojure.lang.Ratio

#"hel+o" java.util.regex.Pattern

15Sunday, September 18, 2011

Literals

example Java type

nil null

true false Boolean

println even? + clojure.lang.Symbol

:beta ::gamma clojure.lang.Keyword

16Sunday, September 18, 2011

Data Structures

type example properties

list (1 2 3) singly-linked,grow at front

vector [1 2 3] indexed,grow at end

map {:a 1, :b 20} key/value pairs

set #{1 7 3} unordered, unique keys

17Sunday, September 18, 2011

Commas,, are,,,,,,whitespace,,,,,

18Sunday, September 18, 2011

Comments

;;; File-level comment

(let [x 6, y 7] ;; Block-level comment, ;; indented like code (println "Hello, World!") (* 6 7)) ; end-of-line comment

19Sunday, September 18, 2011

Structure

(println "Hello, World!")

listsymbol string

20Sunday, September 18, 2011

Semantics

(println "Hello, World!")

function call argument

function

21Sunday, September 18, 2011

defn Semantics

(defn greet "Returns a friendly greeting" [your-name] (str "Hello, " your-name))

define a fndocstring

arguments

fn name

fn body

22Sunday, September 18, 2011

defn Structure

(defn greet "Returns a friendly greeting" [your-name] (str "Hello, " your-name))

listsymbol

string

vector

23Sunday, September 18, 2011

All forms created equalform syntax example

function list (println "hello")

"operator" list (+ 1 2)

method call list (.trim " hello ")

loading list (require 'mylib)

metadata list (with-meta obj m)

control flow list (when valid? (proceed))

scope list (let [x 5] ...)

24Sunday, September 18, 2011

Invocation Forms

(op ...)

• Special Form• Macro• Function

or any invocable thing• Expression which returns

an invocable thing

25Sunday, September 18, 2011

Invocation Forms

user=> (1 2 3)ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn

26Sunday, September 18, 2011

Invocation Forms

user=> (1 2 3)ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn

invocable things

not an invocable thing

27Sunday, September 18, 2011

14 Special Forms

def if fn letloop recur do

new . throw tryset! quote var

28Sunday, September 18, 2011

Special Form: def

(def symbol value-expr?)

29Sunday, September 18, 2011

Special Form: def

user=> (def answer (* 6 7))#'user/answeruser=> answer42 Var

30Sunday, September 18, 2011

Special Form: if

(if condition then-expr else-expr?)

31Sunday, September 18, 2011

Special Form: if

user=> (if (even? 42) "even" "odd")"even"user=> (if (even? 7) "even")nil

32Sunday, September 18, 2011

Truthiness

Clojure Java Common Lisp

Scheme

null value

boolean values

"falsey"

"truthy"

nil null nil or ()

true / false true / false t / nil #t / #f

nil or false false nil or () #f

everything else true everything else

everything else

33Sunday, September 18, 2011

Special Form: do

(do exprs*)

34Sunday, September 18, 2011

Special Form: do

user=> (do 1 2 3)3user=> (do (println 42 "is even") 42)42 is even42

35Sunday, September 18, 2011

Special Form: do

user=> (if (even? 42) (do (println 42 "is even") 42)))42 is even42

36Sunday, September 18, 2011

Macro: when

(when condition exprs*)

(if condition (do exprs*))

37Sunday, September 18, 2011

Macro: when

user=> (when (even? 42) (println 42 "is even") 42)42 is even42

38Sunday, September 18, 2011

Special Form: quote

(quote form)

'form

39Sunday, September 18, 2011

Special Form: quote

user=> (1 2 3)ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn

user=> (quote (1 2 3))(1 2 3)user=> '(1 2 3)(1 2 3)user=> (list 1 2 3)(1 2 3)

40Sunday, September 18, 2011

Special Form: let

(let [bindings*] exprs*)

41Sunday, September 18, 2011

Special Form: let

user=> (let [x 6, y 7] (* x y))42

Binding forms

Value expressions

42Sunday, September 18, 2011

Special Form: let

user=> (let [x 6 y (+ x 1)] (* x y))42

Earlier bindingsavailable

43Sunday, September 18, 2011

Special Form: let

user=> (let [x 6 y (+ x 1)] (println (* x y)) (let [y 10] (println (* x y))))4260nil Rebinding is allowed

44Sunday, September 18, 2011

Special Form: let

user=> (let [x 5] (let [y x] (let [y y] (let [z (+ x y)] z))))

45Sunday, September 18, 2011

Special Form: fn

(fn [params*] exprs*)

(fn ([params*] exprs*)+)

46Sunday, September 18, 2011

Special Form: fn

user=> (fn [x] (+ x 5))#<user$eval1456$fn__1457>user=> (def add5 (fn [x] (+ x 5)))#'user/add5user=> (add5 10)15

compiled fn

47Sunday, September 18, 2011

Macro: defn

(defn symbol [params*] exprs*)

(def symbol (fn [params*] exprs*))

48Sunday, September 18, 2011

Arity

user=> (defn greet ([] (greet "Clojure" "programmer")) ([name] (greet name "the programmer")) ([first-name last-name] (println "Hello," first-name last-name)))#'user/greetuser=> (greet)Hello, Clojure programmerniluser=> (greet "Stuart")Hello, Stuart the programmerniluser=> (greet "Stuart" "Sierra")Hello, Stuart Sierranil

49Sunday, September 18, 2011

Variadic

user=> (defn greet ([name] (println "Hello," name)) ([name & others] (println "Hello," name "and friends" others)))#'user/greetuser=> (greet "Stuart")Hello, Stuartniluser=> (greet "Stuart" "Aaron" "Fogus" "Chouser")Hello, Stuart and friends (Aaron Fogus Chouser)nil

50Sunday, September 18, 2011

Working with Data

51Sunday, September 18, 2011

Value Equality

user=> (= [1 2 3] [1 2 3])trueuser=> (= [1 2 3] [1.0 2.0 3.0])trueuser=> (= [1 2 3] '(1 2 3))true

52Sunday, September 18, 2011

Reference Equality

user=> (= (StringBuilder. "a") (StringBuilder. "a"))false user=> (identical? [1 2 3] [1 2 3])falseuser=> (identical? 2.0 2)false

53Sunday, September 18, 2011

Reference Equality

user=> (= :a :a)true user=> (identical? :a :a)trueuser=> (= 'a 'a)trueuser=> (identical? 'a 'a)false

54Sunday, September 18, 2011

Collections

user=> (count [:a :b :c])3user=> (coll? [:a :b :c])trueuser=> (vector? [:a :b :c])trueuser=> (list? [:a :b :c])false

55Sunday, September 18, 2011

• List

• Vector

Sequential Things

56Sunday, September 18, 2011

Sequential Things

user=> (def v [:a :b :c :d])#'user/vuser=> (first v):auser=> (second v):buser=> (def w (vector 10 11 12 13))#'user/wuser=> (nth w 3)13

57Sunday, September 18, 2011

conj

user=> (def v [:a :b :c :d])#'user/vuser=> (conj v :more)[:a :b :c :d :more]

user=> (def lst (list 1 2 3 4))#'user/lstuser=> (conj lst :more)(:more 1 2 3 4)

Vectors growat the end

Lists growat the front

58Sunday, September 18, 2011

Associative Things

• Map

• Hash map

• Array map

• Vector (sometimes)

59Sunday, September 18, 2011

Maps: get

user=> (def m {:a 1 :b 2})#'user/muser=> (get m :a)1user=> (m :a)1user=> (:a m)1

Maps areinvocable

So are keywords

60Sunday, September 18, 2011

Maps: assoc

user=> (def m (hash-map :a 1 :b 2))#'user/muser=> (assoc m :c 3 :d 4){:a 1, :c 3, :b 2, :d 4}user=> (assoc m :a 17){:a 17, :b 2} new map

with addedkey-value pairs

61Sunday, September 18, 2011

Maps

user=> (def m {:a 1 :b 2})#'user/muser=> (dissoc m :a){:b 2}user=> (keys m)(:a :b)user=> (conj m [:c 3]){:a 1, :c 3, :b 2}

conj on a maptakes a vector pair

62Sunday, September 18, 2011

Maps: merge

user=> (def m {:a 1 :b 2})#'user/muser=> (merge m {:b 17 :c 22}){:a 1, :c 22, :b 17}

63Sunday, September 18, 2011

Maps: zipmap

user=> (zipmap [:a :b :c] [1 2 3]){:c 3, :b 2, :a 1}

64Sunday, September 18, 2011

Maps: get-in

user=> (def person {:name {:first "Stuart" :last "Sierra"} :address {:city "Brooklyn" :state "New York"}})#'user/personuser=> (:first (:name person))"Stuart"user=> (get-in person [:name :first])"Stuart"

65Sunday, September 18, 2011

Maps: assoc-in

user=> (def person {:name {:first "Stuart" :last "Sierra"} :address {:city "Brooklyn" :state "New York"}})#'user/personuser=> (assoc-in person [:name :last] "Halloway"){:name {:last "Halloway", :first "Stuart"}, :address {:state "New York", :city "Brooklyn"}}

66Sunday, September 18, 2011

Vectors are Associative

user=> (def v [:a :b :c])#'user/vuser=> (assoc v 1 "Hello")[:a "Hello" :c]

67Sunday, September 18, 2011

Sets

user=> (def s #{1 2 3})#'user/suser=> s#{1 2 3}user=> (conj s 17)#{1 2 3 17}user=> (conj s 2)#{1 2 3}

68Sunday, September 18, 2011

Sets

user=> (def v [1 2 3 1 2 3 4])#'user/vuser=> (set v)#{1 2 3 4}

69Sunday, September 18, 2011

Sets: contains?

user=> (def s #{1 2 3})#'user/suser=> (contains? s 3)trueuser=> (contains? s 17)false

Checks keys,not values

70Sunday, September 18, 2011

Sets: invocation

user=> (def s #{1 2 3})#'user/suser=> (s 3)3user=> (s 17)nil

Returns objectif it's in the set

71Sunday, September 18, 2011

Destructuring

72Sunday, September 18, 2011

Destructuring

user=> (def stuff [7 8 9 10])#'user/stuff

user=> (let [[a b c d] stuff] (list (+ a b) (+ c d))) (15 19)

73Sunday, September 18, 2011

Destructuring

(let [bindings*] exprs*)

74Sunday, September 18, 2011

Destructuring

(let [binding-form value-expr] exprs*)

75Sunday, September 18, 2011

Sequential Destructuring

(let [[a b c d] stuff] exprs*)

Binding form Value expression

76Sunday, September 18, 2011

(let [[a b c d] stuff] ...

(let [[a b c d] [7 8 9 10]] ...Evaluate

(let [a 7 b 8 c 9 d 10] ...

Destructure

Sequential Destructuring

77Sunday, September 18, 2011

user=> (def stuff [7 8 9 10])#'user/stuff

user=> (let [[a & others] stuff] (println a) (println others))7(8 9 10)nil

Sequential Destructuring

78Sunday, September 18, 2011

(let [[symbols+ & symbol] expr] exprs*)

Get the first one or more elements

Get all remaining elements

Sequential Destructuring

79Sunday, September 18, 2011

Associative Destructuring

user=> (def m {:a 7 :b 4})#'user/muser=> (let [{a :a, b :b} m] [a b])[7 4]

80Sunday, September 18, 2011

user=> (def m {:a 7 :b 4})#'user/muser=> (let [{:keys [a b]} m] [a b])[7 4]

Associative Destructuring

81Sunday, September 18, 2011

Keyword Destructuring

user=> (def m {:a 7 :b 4})#'user/muser=> (let [{:keys [a b c]} m] [a b c])[7 4 nil]

82Sunday, September 18, 2011

Destructuring with Default Values

user=> (def m {:a 7 :b 4})#'user/muser=> (let [{:keys [a b c] :or {c 3}} m] [a b c])[7 4 3]

83Sunday, September 18, 2011

Destructuring

(fn [params*] exprs*)

(defn symbol [params*] exprs*)

Destructuringworks here too

84Sunday, September 18, 2011

Nested Destructuring

user=> (def data {:a [1 2 3] :b {:c 4}})#'user/data

user=> (let [{[x & y] :a {:keys [c d] :or {d 10}} :b} data] (+ x c d))

???

85Sunday, September 18, 2011

Higher-Order Functions

86Sunday, September 18, 2011

apply

user=> (def v [1 2 3 4])#'user/vuser=> (println v)[1 2 3 4]niluser=> (apply println v)1 2 3 4niluser=> (println 1 2 3 4)1 2 3 4nil

87Sunday, September 18, 2011

map

user=> (def v [1 2 3 4])#'user/vuser=> (map (fn [x] (* 5 x)) v)(5 10 15 20)

88Sunday, September 18, 2011

#() syntax

user=> (map (fn [x] (* 5 x)) v)(5 10 15 20)user=> (map #(* 5 %) v)(5 10 15 20) Same fn

89Sunday, September 18, 2011

map

user=> (def v [:a :b :c])#'user/vuser=> (def w [10 20 30 40 50])#'user/nuser=> (map vector v w)([:a 10] [:b 20] [:c 30])

90Sunday, September 18, 2011

reduce

user=> (reduce + [1 2 3 4])10user=> (+ (+ (+ 1 2) 3) 4)10

91Sunday, September 18, 2011

reduce

user=> (reduce + 100 [1 2 3 4])110user=> (+ (+ (+ (+ 100 1) 2) 3) 4)110

seed value

92Sunday, September 18, 2011

reduce

user=> (reduce (fn [m [k v]] (assoc m (name k) (+ 100 v))) {} {:a 1 :b 2}){"b" 102, "a" 101}

destructurekey-value pair

seed value

93Sunday, September 18, 2011

filter and remove

user=> (filter even? [1 2 3 4 5])(2 4)user=> (filter (set "aeiou") "Hello, World!")(\e \o \o)user=> (apply str (remove (set "aeiou") "Hello, World!"))"Hll, Wrld!"

94Sunday, September 18, 2011

Maps: assoc-in

user=> (def person {:name {:first "Stuart" :last "Sierra"} :address {:city "Brooklyn" :state "New York"}})#'user/personuser=> (assoc-in person [:name :last] "Halloway"){:name {:last "Halloway", :first "Stuart"}, :address {:state "New York", :city "Brooklyn"}}

95Sunday, September 18, 2011

Maps: update-in

user=> (def person {:name {:first "Stuart" :last "Sierra"} :address {:city "Brooklyn" :state "New York"}})#'user/personuser=> (update-in person [:name :last] #(.toUpperCase %)){:name {:last "SIERRA", :first "Stuart"}, :address {:state "New York", :city "Brooklyn"}}

96Sunday, September 18, 2011

identity

user=> (doc identity)-------------------------clojure.core/identity([x]) Returns its argument.nil

97Sunday, September 18, 2011

filter and identity

user=> (def v [1 2 3 nil 4 5 nil 6])#'user/vuser=> (filter identity v)(1 2 3 4 5 6)

98Sunday, September 18, 2011

fnil

user=> (doc fnil)-------------------------clojure.core/fnil([f x] [f x y] [f x y z]) Takes a function f, and returns a function that calls f, replacing a nil first argument to f with the supplied value x.

99Sunday, September 18, 2011

fnil

user=> (+ nil 3)NullPointerException clojure.lang.Numbers.opsuser=> (def add (fnil + 0))#'user/adduser=> (add nil 3)3

100Sunday, September 18, 2011

update-in and fnil

user=> (def m {:foo {:a 1 :b 2} :bar {:c 3}})#'user/muser=> (update-in m [:foo :a] inc){:foo {:a 2, :b 2}, :bar {:c 3}}user=> (update-in m [:baz :d] inc)NullPointerException clojure.lang.Numbers.opsuser=> (update-in m [:baz :d] (fnil inc 0)){:foo {:a 1, :b 2}, :bar {:c 3}, :baz {:d 1}}

101Sunday, September 18, 2011

frequencies

user=> (reduce (fn [m c] (update-in m [c] (fnil inc 0))) {} "a short sharp shock"){\space 3, \a 2, \c 1, \h 3, \k 1, \o 2, \p 1, \r 2, \s 3, \t 1}

user=> (frequencies "a short sharp shock"){\space 3, \a 2, \c 1, \h 3, \k 1, \o 2, \p 1, \r 2, \s 3, \t 1}

102Sunday, September 18, 2011

Sequences

103Sunday, September 18, 2011

Lists

first next first next first next

lst

nil

(def lst '(1 2 3))

1 2 3

104Sunday, September 18, 2011

Sequences

lst

(def lst (range 1 4))#'user/lst

LazySeq

fn

105Sunday, September 18, 2011

Sequences

lst

(first lst)1

LazySeq

first next

1

LazySeq

fn

106Sunday, September 18, 2011

Sequences

lst

(second lst)2

LazySeq

first next

1

LazySeq

first next

2

LazySeq

fn

107Sunday, September 18, 2011

range

(range)

(range end)

(range start end)

(range start end step)

infinite!

108Sunday, September 18, 2011

Infinite Sequences

user=> (map vector (range) [:a :b :c])([0 :a] [1 :b] [2 :c])

user=> (map-indexed vector [:a :b :c])([0 :a] [1 :b] [2 :c])

user=> (zipmap "abc" (range)){\c 2, \b 1, \a 0}

109Sunday, September 18, 2011

repeat

user=> (repeat 5 :a)(:a :a :a :a :a)

user=> (take 10 (repeat :b))(:b :b :b :b :b :b :b :b :b :b)

infinite!

110Sunday, September 18, 2011

seq

user=> (seq [1 2 3])(1 2 3)user=> (seq {:a 1 :b 2 :c 3})([:a 1] [:c 3] [:b 2])user=> (seq #{1 2 3})(1 2 3)user=> (seq [])nil

111Sunday, September 18, 2011

Lazy vs. Strict

(with-open [file ...] (line-seq file))

returns lazy seqof lines in file

file is closed here

112Sunday, September 18, 2011

Lazy vs. Strict

(with-open [file ...] (doall (line-seq file))

force entire seqto be realized

113Sunday, September 18, 2011

doall, dorun, doseq

(doall sequence)

(dorun sequence)

(doseq [symbol sequence] ...body...)

returns sequence

returns nil

returns nil

114Sunday, September 18, 2011

Java Interop

115Sunday, September 18, 2011

Java Types

Clojure Literal Java Type

"hello" java.lang.String

3.14 java.lang.Double

[1 2 3] java.util.List

{"a" 1, "b" 2} java.util.Map

(fn [x] (* x 5)) java.lang.Runnable

116Sunday, September 18, 2011

class and ancestors

user=> (class "hello")java.lang.Stringuser=> (ancestors (class "hello"))#{java.lang.CharSequence java.lang.Comparable java.lang.Object java.io.Serializable}

117Sunday, September 18, 2011

REPL Helpers: javadoc

user=> (javadoc java.io.Writer)"http://java.sun.com/javase/6/docs/api/java/io/Writer.html"

user=> (javadoc "hello")"http://java.sun.com/javase/6/docs/api/java/lang/String.html"

Java class

Object

118Sunday, September 18, 2011

Special Form: . (dot)

(. object method arguments*)

(. object field)

(. class static-method arguments*)

(. class static-field)

119Sunday, September 18, 2011

Instance Method Calls

user=> (. "hello" charAt 0)\h

user=> (.charAt "hello" 0)\h

Syntactic sugar

object method arguments

120Sunday, September 18, 2011

Static Method Calls

user=> (. Long valueOf "42")42

user=> (Long/valueOf "42")42

Syntactic sugar

121Sunday, September 18, 2011

Static Fields

user=> (. Math PI)3.141592653589793

user=> Math/PI3.141592653589793

Syntactic sugar

122Sunday, September 18, 2011

Constructors

user=> (new java.io.File "/home")#<File /home>

user=> (java.io.File. "/home")#<File /home>

Syntactic sugar

Constructorargumentsclass name

123Sunday, September 18, 2011

Java Import

user=> (import (java.net URL URI))java.net.URIuser=> (URL. "http://clojure.org/")#<URL http://clojure.org/>

Package Classes"prefix list"

124Sunday, September 18, 2011

try/catch/finally

(try ... expressions ... (catch Class name ... handle exception ...) (finally ... always do this ...))

125Sunday, September 18, 2011

throw

(throw exception)

126Sunday, September 18, 2011

throw and *e

user=> (throw (Exception. "Boom!"))Exception Boom! user/eval11 (NO_SOURCE_FILE:5)user=> *e#<RuntimeException java.lang.RuntimeException: java.lang.Exception: Boom!>

constructor

127Sunday, September 18, 2011

print stack trace

user=> (pst)Exception Boom! user/eval11 (NO_SOURCE_FILE:5) clojure.lang.Compiler.eval (Compiler.java:6424) clojure.lang.Compiler.eval (Compiler.java:6390) clojure.core/eval (core.clj:2795) clojure.main/repl/read-eval-print--5967 (main.clj:244)

defined in clojure.repl

128Sunday, September 18, 2011

Java Interop Summary

Special Form Sugar

Instance Method

Instance Field

Static Method

Static Field

Constructor

(. obj method args*) (.method obj args*)

(. obj field) (.field obj)

(. Class method args*) (Class/method args*)

(. Class field) Class/field

(new Class args*) (Class. args*)

129Sunday, September 18, 2011

Java Nested Classes

Package-QualifiedClass Name

UnqualifiedClass Name

Regular Class

Inner Class

java.io.File File

java.util.Map$Entry Map$Entry

130Sunday, September 18, 2011

Libraries

131Sunday, September 18, 2011

Java Classpath

Clojure source code in ./src/JAR files in ./lib/

java -cp src:lib/* clojure.main

classpath

132Sunday, September 18, 2011

Project Management

• Leiningen

• Cake

• Maven

• Ant

133Sunday, September 18, 2011

MavenDirectory Structure

pom.xmlsrc/main/clojure/ your/project/file.cljsrc/test/clojure/ your/project/file_test.cljtarget/classes/ compiled_file.class$HOME/.m2/repository/ org/clojure/clojure/1.3.0/clojure-1.3.0.jar

134Sunday, September 18, 2011

LeiningenDirectory Structure

project.cljsrc/ your/project/file.cljtest/ your/project/file_test.cljclasses/ compiled_file.classlib/ clojure-1.3.0.jar

135Sunday, September 18, 2011

Leiningen project.clj

(defproject my.project.name "1.0.0" :description "My cool Clojure project." :dependencies [[org.clojure/clojure "1.3.0"] [org.clojure/data.zip "0.1.0"]])

groupId artifactId version

136Sunday, September 18, 2011

Leiningen Commands$ lein helpLeiningen is a build tool for Clojure.

Several tasks are available: pom help jar test deps ... repl new

Run lein help $TASK for details.See http://github.com/technomancy/leiningen as well.

137Sunday, September 18, 2011

Finding Dependencies

• search.maven.org

• jarvana.com

• clojars.org

138Sunday, September 18, 2011

clojure-contribup to 1.2

• One big library

• Version number matches Clojure

• Mixed quality

Clojureclojure-contrib

1.0.0 1.0.0

1.1.0 1.1.0

1.2.01.2.1 1.2.0

139Sunday, September 18, 2011

clojure-contribafter 1.2

• Many small libraries

• Independent version numbers

• Compatible withClojure 1.2 and 1.3

• Mixed quality

algo.monadscore.incubator

core.logiccore.match

core.unifydata.csv

data.finger-treedata.json

data.priority-mapdata.xmldata.zip

java.classpathjava.datajava.jdbcjava.jmx

math.combinatoricsmath.numeric-tower

test.generativetools.cli

tools.loggingtools.macro

tools.namespacetools.nrepltools.tracedev.clojure.org/display/doc/Clojure+Contrib

140Sunday, September 18, 2011

Included in Clojure• clojure.inspector

• clojure.java.io

• clojure.java.browse

• clojure.java.shell

• clojure.reflect

• clojure.repl

• clojure.string

• clojure.set

• clojure.test

• clojure.walk

• clojure.xml

• clojure.zip

141Sunday, September 18, 2011

Namespaces

142Sunday, September 18, 2011

The REPL

user=> (+ 1 2 3)6user=>

"you arehere"

143Sunday, September 18, 2011

Namespaces

user=> (ns my.cool.thing)nilmy.cool.thing=>

"you are here"

144Sunday, September 18, 2011

Qualified Symbols

user=> (ns foo.bar)nilfoo.bar=> (defn hello [] (println "Hello, World!"))#'foo.bar/hellofoo.bar=> (ns baz.quux)nilbaz.quux=> (foo.bar/hello)Hello, World!nil

Namespace-qualifiedsymbol

145Sunday, September 18, 2011

Namespaces and Files

$CLASSPATH/my/cool/thing.clj

(ns my.cool.thing)

dots become slashes

146Sunday, September 18, 2011

Names and Hyphens

$CLASSPATH/my/cool/web_app.clj

(ns my.cool.web-app)

hyphens become underscores

147Sunday, September 18, 2011

Macro: ns

(ns name references*)

148Sunday, September 18, 2011

ns :require

(ns my.cool.project (:require [some.ns.foo :as foo]))

(foo/function-in-foo)

ns alias

149Sunday, September 18, 2011

ns :use

(ns my.cool.project (:use [some.ns.foo :only (a b)]))

(a)(b) list of

symbols

unqualifiedsymbols

150Sunday, September 18, 2011

ns :use

(ns my.cool.project (:use some.ns.foo))

(a)(b)

unqualified symbolsfrom anywhere

151Sunday, September 18, 2011

ns :import

(ns my.cool.project (:import (java.io File Writer))

packagename

classnames

152Sunday, September 18, 2011

Macro: ns

(ns name (:require [some.ns.foo :as foo] [other.ns.bar :as bar]) (:use [this.ns.baz :only (a b c)] [that.ns.quux :only (d e f)]) (:import (java.io File FileWriter) (java.net URL URI))

153Sunday, September 18, 2011

require in the REPL

user=> (require '[clojure.set :as set])niluser=> (set/union #{1 2} #{2 3 4})#{1 2 3 4}

arguments mustbe quoted

154Sunday, September 18, 2011

use in the REPL

user=> (use 'clojure.string)WARNING: replace already refers to: #'clojure.core/replace in namespace: user, being replaced by: #'clojure.string/replaceWARNING: reverse already refers to: #'clojure.core/reverse in namespace: user, being replaced by: #'clojure.string/reverseniluser=> (reverse "hello")"olleh"

arguments mustbe quoted

155Sunday, September 18, 2011

RELP Helpers: dir

user=> (dir clojure.repl)aproposdemungedirdir-fndocfind-docpstroot-causeset-break-handler!sourcesource-fnstack-element-strthread-stoppernil

156Sunday, September 18, 2011

Concurrency

157Sunday, September 18, 2011

Concurrency

Parallelism

State

158Sunday, September 18, 2011

class Invoice { private Date date;

public Date getDate() { return this.date; }

public void setDate(Date date) { this.date = date; }}

159Sunday, September 18, 2011

class Date { public void setDay(int day); public void setMonth(int month); public void setYear(int year);}

Mutable!

160Sunday, September 18, 2011

class Invoice { private Date date;

public Date getDate() { return this.date; }

public void setDate(Date date) { this.date = date; }}

Better notchange it!

Better notchange it!

161Sunday, September 18, 2011

class Invoice { private Date date;

public Date getDate() { return this.date.clone(); }

public void setDate(Date date) { this.date = date.clone(); }}

Defensivecopying

162Sunday, September 18, 2011

Programming with immutable values

means never having to say you're sorry.

163Sunday, September 18, 2011

Sept 18

today

164Sunday, September 18, 2011

Sept 18 Sept 19

today

165Sunday, September 18, 2011

Sept 18

Identity

State

Sept 19

today

Value Value

166Sunday, September 18, 2011

Sept 18

Identity

State

Sept 19

today

function

Value Value

function

167Sunday, September 18, 2011

Sept 18

Identity

State

Past

Sept 19Sept 17 function

Present Future

function

today

168Sunday, September 18, 2011

Sept 18

Identity

State

Past

Sept 19Sept 17 function

Present Future

function

today

The future is a function of the past.

169Sunday, September 18, 2011

Mutable References

Ref Atom

Var Agent

170Sunday, September 18, 2011

readers

Atomwriter

writer

abortretry

171Sunday, September 18, 2011

Atom(def tick (atom 1))(deref tick) 1

tick

1

172Sunday, September 18, 2011

Atom(def tick (atom 1))(deref tick) 1

(swap! tick inc)@tick 2

tick

1

2

inc

173Sunday, September 18, 2011

Atom(def tick (atom 1))(deref tick) 1

(swap! tick inc)@tick 2

(swap! tick + 10)@tick 12

tick

2

12

+10

174Sunday, September 18, 2011

value value value value

value value value value

value value value value

identity

identityidentity

175Sunday, September 18, 2011

value value value value

value value value value

value value value value

identity

identityidentity

176Sunday, September 18, 2011

Refwriter

writer

readers

abortretryRef

transaction

177Sunday, September 18, 2011

Ref(def A (ref 1))(def B (ref 10))

A 1

10B

178Sunday, September 18, 2011

Ref(def A (ref 1))(def B (ref 10))

(dosync (alter A inc) (alter B + 10))

A 1

10

20

inc

+10

B

2

transaction

179Sunday, September 18, 2011

Ref(def A (ref 1))(def B (ref 10))

(dosync (alter A inc) (alter B + 10))

A

20

B

2

@A 2@B 20

180Sunday, September 18, 2011

AtomicConsistentIsolatedDurable

Database Transactions

181Sunday, September 18, 2011

AtomicConsistentIsolated

Clojure Transactions

182Sunday, September 18, 2011

Agentactionaction

readers

action queue

Agent Thread Pool

183Sunday, September 18, 2011

Agent(def A (agent 1))

A 1queue

184Sunday, September 18, 2011

Agent(def A (agent 1))

(send A inc)@A 1

A 1inc

queue

185Sunday, September 18, 2011

Agent(def A (agent 1))

(send A inc)@A 1

A 1inc

2@A 2

queue

186Sunday, September 18, 2011

Varroot

binding

thread-local

binding

thread-local

binding

other threads

187Sunday, September 18, 2011

Ref Atom

Var Agent

Concurrency

188Sunday, September 18, 2011

Macros

189Sunday, September 18, 2011

You

Lexer/Parser

Characters

AbstractSyntax Tree

Compiler/Interpreter

190Sunday, September 18, 2011

Clojure Reader

ClojureCompiler

You Characters

Data Structures

191Sunday, September 18, 2011

Clojure Reader

You Characters

Data Structures

Macros

ClojureCompiler

192Sunday, September 18, 2011

read-string and eval

user=> (read-string "(println 1 2 3)")(println 1 2 3)

user=> (eval *1)1 2 3nil

193Sunday, September 18, 2011

Macro: when

(when condition exprs*)

(if condition (do exprs*))

194Sunday, September 18, 2011

defmacro

(defmacro when [test & body] (list 'if test (cons 'do body)))

name parameters

construct codeto return

195Sunday, September 18, 2011

macroexpand

user=> (macroexpand '(when a b c d))(if a (do b c d))

quoted expression

expanded result

196Sunday, September 18, 2011

How to Write a Macro

Form you want to write

Form you wantit to become

functioninput output

197Sunday, September 18, 2011

How to Write a Macro

;; we want to write: ;; and have it become:(when foo (if foo (dothis) (do (dothat)) (dothis) (dothat))) ;; from core.clj(defmacro when [test & body] (list 'if test (cons 'do body)))

;; use macroexpand to try ituser=> (macroexpand '(when foo (dothis) (dothat)))(if foo (do (dothis) (dothat)))

198Sunday, September 18, 2011

Macro Expansion

(when a b c d)

Macro: when

(if a (do b c d))

arguments arenot evaluated

199Sunday, September 18, 2011

syntax-quote

(defmacro when [test & body] `(if ~test (do ~@body)))

syntax-quote unquote splicingunquote

200Sunday, September 18, 2011

syntax-quote

user=> (def x 5)#'user/xuser=> (def lst '(:a :b :c))#'user/lstuser=> `(x ~x ~lst)(user/x 5 (:a :b :c))user=> `(x ~x ~@lst)(user/x 5 :a :b :c)

201Sunday, September 18, 2011

gensym

user=> (gensym "foo")foo39user=> (gensym "foo")foo42

202Sunday, September 18, 2011

user=> `(let [x 1] x)(clojure.core/let [user/x 1] user/x)

user=> `(let [x# 1] x#)(clojure.core/let [x__29__auto__ 1] x__29__auto__)

generatedsymbol

auto-gensymqualified symbolnot allowed here

203Sunday, September 18, 2011

Recursion

204Sunday, September 18, 2011

Recursive GCD

user=> (defn gcd [x y] ; x >= y (if (zero? y) x (gcd y (rem x y))))#'user/gcduser=> (gcd 100 35)5user=> (gcd 37 22)1

205Sunday, September 18, 2011

Recursive GCD

user=> (defn gcd [x y] ; x >= y (if (zero? y) x (gcd y (rem x y))))

tail position

206Sunday, September 18, 2011

GCD with recur

user=> (defn gcd [x y] ; x >= y (if (zero? y) x (recur y (rem x y))))

tail position

207Sunday, September 18, 2011

Recursive Fibonacci

user=> (defn fib [n] (cond (zero? n) 0 (= 1 n) 1 :else (+ (fib (dec n)) (fib (- n 2)))))#'user/fibuser=> (fib 10)55user=> (fib 50) ; wait a really long time

208Sunday, September 18, 2011

Fibaonacci Helper

user=> (defn fib-step [a b n] (if (= 1 n) b (recur b (+ a b) (dec n))))#'user/fib-stepuser=> (defn fib [n] (fib-step 0 1 n))#'user/fibuser=> (fib 50)12586269025

209Sunday, September 18, 2011

loop / recur

user=> (defn fib [n] (loop [a 0, b 1, i n] (if (= 1 i) b (recur b (+ a b) (dec i)))))#'user/fibuser=> (fib 50)12586269025

210Sunday, September 18, 2011

loop / recur

(loop [initialization] (if termination-condition return-value (recur updated-variables)))

211Sunday, September 18, 2011

More

212Sunday, September 18, 2011

Clojure

• clojure.org

• clojure.blip.tv

• dev.clojure.org

• groups.google.com/group/clojure

• #clojure on irc.freenode.net

213Sunday, September 18, 2011

Fun

• github.com/relevance/labrepl

• 4clojure.com

• github.com/functional-koans/clojure-koans

214Sunday, September 18, 2011