Functional Programming with Clojure

48
with by Carlo Sciolla [email protected]

Transcript of Functional Programming with Clojure

Page 3: Functional Programming with Clojure

The package contains● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation

with

Page 4: Functional Programming with Clojure

with

The package contains● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation

Page 5: Functional Programming with Clojure

with

Brief intro to Clojure● I will trade precision for clarity

● there’s much more to know

● one huge missing topic: the REPL

● you can try this at home

Page 6: Functional Programming with Clojure

with

Clojure data anatomy

1 2.0 3/4 ; numbersfoo bar ; symbols:one :two ; keywords“value” ; stringstrue false ; bools\a \b \c ; charsnil ; null

Page 7: Functional Programming with Clojure

with

Clojure data anatomy

[1 2 3] ; vector‘(foo bar) ; list#{:one :two} ; set{:key “value”} ; map

Page 8: Functional Programming with Clojure

with

Clojure data anatomy

[1 2 3] ; vector‘(foo bar) ; list#{:one :two} ; set{:key “value”} ; map

Page 9: Functional Programming with Clojure

with

Clojure code anatomy

(* 132.715 (- 1.06 1.02))

-> 5.308600000000005nested unquoted lists, in facts:

“The name LISP derives from "LISt Processing".” -- Wikipedia

Page 10: Functional Programming with Clojure

with

Clojure code anatomy

(* 132.715 (- 1.06 1.02))

-> 5.308600000000005no “return”: everything is an expression

Page 11: Functional Programming with Clojure

with

Clojure beer anatomy

(* 132.715 (- 1.06 1.02))

-> 5.31º

Alcohol by volume formula (Wikipedia):

Page 12: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

*

132.715 -

1.06 1.02

Page 13: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

*

132.715 -

1.06 1.02

Page 14: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715 -

1.06 1.02

The symbol * evaluates to:clojure.core/_STAR_

Page 15: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715 -

1.06 1.02

Values evaluate to themselves

Page 16: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715 -

1.06 1.02

Page 17: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715

SUB

1.06 1.02

The symbol - evaluates to:clojure.core/_

Page 18: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715

SUB

1.06 1.02

Values evaluate to themselves

Page 19: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715

SUB

1.06 1.02

Values evaluate to themselves

Page 20: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715

SUB

1.06 1.02

All args evaluated? Function call!

Page 21: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715

0.04

All args evaluated? Function call!

Page 22: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715

0.04

All args evaluated? Function call!

Page 23: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

5.31

(* 132.715 (- 1.06 1.02))

All args evaluated? Function call!

Page 24: Functional Programming with Clojure

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

Page 25: Functional Programming with Clojure

with

Naming stuff: global bindings

(def scalar 42)

(def fun (fn [a b] (+ a b)))

(defn moar-fun [a b] (+ a b)))

Page 26: Functional Programming with Clojure

with

Naming stuff: lexical bindings

(let [one “one” key (keyword one)] key)

; => :one

Page 27: Functional Programming with Clojure

with

Ready to go● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation

Page 28: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(defn compose [f g] (fn [x] (f (g x))))

Page 29: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(defn compose [f g] (fn [x] (f (g x))))

returns a function

accepts functions in input

Page 30: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(defn compose [f g] (fn [x] (f (g x))))

((compose inc dec) 42); => 42

Page 31: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(let [foo [{:pi 3.14} {:g 9.8}]] (conj foo {:phi 1.62}))

; => [{:pi 3.14} {:g 9.8} {:phi 1.63}]

Page 32: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(let [foo [{:pi 3.14} {:g 9.8}]] (conj foo {:phi 1.62}) (count foo)) ; => 2

3.14:pi

foo foo’

9.8:g 1.62:phi

Page 33: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(doseq [_ (range 2000)] (inc 41)) ; => always 42

For a given input, pure functions yield the same result, making them dead-easy to maintain and prove correct

Page 34: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(doseq [_ (range 2000)] (rand) (http/GET “http://...”))

Impure code enables interaction, but introduces side effects which make your program harder to test and reason about

Page 35: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(defn my-inc [[h & t]] (when h (cons (inc h) (my-inc t))))

recursive call

Page 36: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(defn my-inc [[h & t]] (when h (cons (inc h) (my-inc t))))exit condition

Page 37: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation

destructuring: pattern-match your input

(defn my-inc [[h & t]] (when h (cons (inc h) (my-inc t))))

Page 38: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation

def my-inc(s) { def res = [] for(i in s) res << i + 1 res}

(defn my-inc [[h & t]] (when h (cons (inc h) (my-inc t))))

Page 39: Functional Programming with Clojure

with

What if the input is infinite?

(defn my-inc [[h & t]] (when h (cons (inc h) (my-inc t))))

Page 40: Functional Programming with Clojure

with

Kaboom!

(defn my-inc [[h & t]] (when h (cons (inc h) (my-inc t))))

with no tail call optimisation (TCO), recursive invocations blows up the stack

Page 41: Functional Programming with Clojure

with

Working around the lack of TCO

(defn my-inc [s] (loop [res () rem s] (let [[h & t] rem] (if h (recur (cons (inc h) res) t) res))))

Page 42: Functional Programming with Clojure

with

Working around the lack of TCO

(defn my-inc [s] (loop [res () rem s] (let [[h & t] rem] (if h (recur (cons (inc h) res) t) res))))

ECMAScript 6Java 9 (?)

Page 43: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(defn lazy-inc [[h & t]] (lazy-seq (when h (cons (inc h) (lazy-inc t))))

Page 44: Functional Programming with Clojure

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation(defn lazy-inc [[h & t]] (lazy-seq (when h (cons (inc h) (lazy-inc t))))

retuns a “thunk”

Page 45: Functional Programming with Clojure

with

What if the input is infinite?

(defn lazy-inc [[h & t]] (lazy-seq (when h (cons (inc h) (lazy-inc t)))))

Page 46: Functional Programming with Clojure

with

What if the input is infinite?

(defn lazy-inc [[h & t]] (lazy-seq (when h (cons (inc h) (lazy-inc t)))))

Page 47: Functional Programming with Clojure

with

Q / A

Page 48: Functional Programming with Clojure

with

Thanks!

Carlo Sciollap r o f e s s i o n a l t i n k e r e r

https://twitter.com/skuro

https://github.com/skuro

http://skuro.tk

http://amsclj.nl