Functional Programming with Clojure

Post on 15-Jul-2015

277 views 1 download

Tags:

Transcript of Functional Programming with Clojure

withby

Carlo Sciollaskuro@skuro.tk

with

Carlo Sciollaskuro@skuro.tk

works fororganisesfrom

The package contains● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation

with

with

The package contains● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation

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

with

Clojure data anatomy

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

with

Clojure data anatomy

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

with

Clojure data anatomy

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

with

Clojure code anatomy

(* 132.715 (- 1.06 1.02))

-> 5.308600000000005nested unquoted lists, in facts:

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

with

Clojure code anatomy

(* 132.715 (- 1.06 1.02))

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

with

Clojure beer anatomy

(* 132.715 (- 1.06 1.02))

-> 5.31º

Alcohol by volume formula (Wikipedia):

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

*

132.715 -

1.06 1.02

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

*

132.715 -

1.06 1.02

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_

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715 -

1.06 1.02

Values evaluate to themselves

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715 -

1.06 1.02

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/_

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

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

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!

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715

0.04

All args evaluated? Function call!

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

STAR

132.715

0.04

All args evaluated? Function call!

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

5.31

(* 132.715 (- 1.06 1.02))

All args evaluated? Function call!

with

The Reader

Or:HowI

LearnedToStop

WorryingAndLoveTheEval

(* 132.715 (- 1.06 1.02))

with

Naming stuff: global bindings

(def scalar 42)

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

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

with

Naming stuff: lexical bindings

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

; => :one

with

Ready to go● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

● lazy evaluation

with

Functional schmunctional● functions as values

● immutable (persistent) data structures

● pure functions

● recursion

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

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

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

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}]

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

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

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

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

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

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))))

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))))

with

What if the input is infinite?

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

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

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))))

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 (?)

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))))

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”

with

What if the input is infinite?

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

with

What if the input is infinite?

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

with

Q / A

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