clojure values

145
Thinking the Clojure Way Christophe Grand GOTO Cph, May 13th 2011

Upload: cgrand

Post on 15-Jan-2015

663 views

Category:

Technology


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Clojure values

Thinking theClojure Way

Christophe Grand

GOTO Cph, May 13th 2011

Page 2: Clojure values

Rejoice, Clojure is simpleCoding along/againstSinging with

à la carte

Page 3: Clojure values

Rejoice, Clojure is simpleSmall regular syntax

Coding along/againstSinging with

à la carte

Page 4: Clojure values

Rejoice, Clojure is simpleSmall regular syntax

Simple does not mean familiar

Coding along/againstSinging with

à la carte

Page 5: Clojure values

Rejoice, Clojure is simpleSmall regular syntax

Simple does not mean familiar

Simple means not compound

Coding along/againstSinging with

à la carte

Page 6: Clojure values

Rejoice, Clojure is simpleSmall regular syntax

Simple does not mean familiar

Simple means not compound

Clojure is made of simple things

Coding along/againstSinging with

à la carte

Page 7: Clojure values

Rejoice, Clojure is simpleSmall regular syntax

Simple does not mean familiar

Simple means not compound

Clojure is made of simple things

Small set of independent concepts

Coding along/againstSinging with

à la carte

Page 8: Clojure values

Rejoice, Clojure is simpleSmall regular syntax

Simple does not mean familiar

Simple means not compound

Clojure is made of simple things

Small set of independent concepts

One concept at a time

Coding along/againstSinging with

à la carte

Page 9: Clojure values

Rejoice, Clojure is simpleSmall regular syntax

Simple does not mean familiar

Simple means not compound

Clojure is made of simple things

Small set of independent concepts

One concept at a time

Coding along/againstSinging with

à la carte

Page 10: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

State management

One bite at a timefaire 4 groupes :Syntax+FPRec+lazy seqspolymorphism+typesinterop+mutation

les deux derniers blocs devraient être animés pour être mis au même niveau

Page 11: Clojure values

Syntax

Page 12: Clojure values

LiteralsNumbers 42 3.14 3/4 5.01M 43N

Strings "Hello GOTO Cph"

Characters \c \newline

Keywords :a-key

Symbols foo clojure.core/map

Vectors [1 "two" :three]

Maps {:key "val", :key2 42}

Sets #{1 "two" :three}

Regex #"a.*b"

null nil

booleans* true false*anything but false and nil is true

Page 13: Clojure values

What about lists?

Page 14: Clojure values

What about lists?Quoted lists are too literal: '(1 (+ 1 1))

Page 15: Clojure values

What about lists?Quoted lists are too literal: '(1 (+ 1 1))

Displaced as literals by vectors

Page 16: Clojure values

What about lists?Quoted lists are too literal: '(1 (+ 1 1))

Displaced as literals by vectors

Abstracted away by sequences

Page 17: Clojure values

What about lists?Quoted lists are too literal: '(1 (+ 1 1))

Displaced as literals by vectors

Abstracted away by sequences

Survive mostly for code representation

Page 18: Clojure values

( defn abs [n] if neg? n) - n) n))

Lists are for code( ( (

Page 19: Clojure values

( defn abs [n] if neg? n) - n) n))

Lists are for code( ( (

Pro tip: Lisp code is a stereogram

Page 20: Clojure values

( defn abs [n] if neg? n) - n) n))

Lists are for code( ( (

Pro tip: Lisp code is a stereogramCross your eyes to see parens in the right place

Page 21: Clojure values

( defn abs [n] if neg? n) - n) n))

Lists are for code(

( (

Pro tip: Lisp code is a stereogramCross your eyes to see parens in the right place

Page 22: Clojure values

(defn abs [n] (if (neg? n) (- n) n))

Lists are for code

Page 23: Clojure values

(defn abs [n] (if (neg? n) (- n) n))

Lists are for code

function

Page 24: Clojure values

(defn abs [n] (if (neg? n) (- n) n))

Lists are for code

macro

function

Page 25: Clojure values

(defn abs [n] (if (neg? n) (- n) n))

Lists are for code

special form

macro

function

Page 26: Clojure values

That’s all about syntax!

Page 27: Clojure values

Functional Programming

Page 28: Clojure values

Clojure’s FP

Page 29: Clojure values

Clojure’s FPImpure

Page 30: Clojure values

Clojure’s FPImpure

Persistent collections

Page 31: Clojure values

Clojure’s FPImpure

Persistent collections

Strictly evaluated

Page 32: Clojure values

Clojure’s FPImpure

Persistent collections

Strictly evaluated

But lazy sequences

Page 33: Clojure values

Clojure’s FPImpure

Persistent collections

Strictly evaluated

But lazy sequences

Not strictly lazy though!

Page 34: Clojure values

Clojure’s FPImpure

Persistent collections

Strictly evaluated

But lazy sequences

Not strictly lazy though!

Page 35: Clojure values

Persistent collections

Page 36: Clojure values

Persistent collectionsVectors, maps and sets

Page 37: Clojure values

Persistent collectionsVectors, maps and sets

Common usecases:

Page 38: Clojure values

Persistent collectionsVectors, maps and sets

Common usecases:

Vectors as tuples

Page 39: Clojure values

Persistent collectionsVectors, maps and sets

Common usecases:

Vectors as tuples

Vectors as stacks

Page 40: Clojure values

Persistent collectionsVectors, maps and sets

Common usecases:

Vectors as tuples

Vectors as stacks

Maps as data

Page 41: Clojure values

Persistent collectionsVectors, maps and sets

Common usecases:

Vectors as tuples

Vectors as stacks

Maps as data

Map as index, summary

Page 42: Clojure values

Persistent collectionsVectors, maps and sets

Common usecases:

Vectors as tuples

Vectors as stacks

Maps as data

Map as index, summary

Sets as containers, relations

Page 43: Clojure values

Sequences

Page 44: Clojure values

SequencesFirst, what are sequences?

Page 45: Clojure values

SequencesFirst, what are sequences?

Abstraction over linked lists

Page 46: Clojure values

SequencesFirst, what are sequences?

Abstraction over linked lists

List-like views over data

Page 47: Clojure values

SequencesFirst, what are sequences?

Abstraction over linked lists

List-like views over data

Support first and rest

Page 48: Clojure values

SequencesFirst, what are sequences?

Abstraction over linked lists

List-like views over data

Support first and rest

Replace iterators

Page 49: Clojure values

SequencesFirst, what are sequences?

Abstraction over linked lists

List-like views over data

Support first and rest

Replace iterators

Replace indices

Page 50: Clojure values

Lazy sequences

Page 51: Clojure values

Lazy sequencesSequences evaluated (realized) on demand

Page 52: Clojure values

Lazy sequencesSequences evaluated (realized) on demand

Allow to process big data

Page 53: Clojure values

Lazy sequencesSequences evaluated (realized) on demand

Allow to process big data

or big intermediate values

Page 54: Clojure values

Lazy sequencesSequences evaluated (realized) on demand

Allow to process big data

or big intermediate values

(->> (slurp "access.log") split-lines (map count) (filter odd?))

Page 55: Clojure values

Lazy sequences

Doesn’t matter w/ strict evaluation

Page 56: Clojure values

Lazy sequencesRealization can go ahead of consumption

Doesn’t matter w/ strict evaluation

Page 57: Clojure values

Lazy sequencesRealization can go ahead of consumption

Not suitable for control flow Doesn’t matter w/ strict evaluation

Page 58: Clojure values

Lazy sequencesRealization can go ahead of consumption

Not suitable for control flow

Better locality, less churn

Doesn’t matter w/ strict evaluation

Page 59: Clojure values

That’s all about FP!

Page 60: Clojure values

Clojure spirit

Page 61: Clojure values

Clojure spirit

Page 62: Clojure values

Clojure spiritPragmatism

Page 63: Clojure values

Clojure spiritPragmatism

Correctness

Page 64: Clojure values

Clojure spiritPragmatism

Correctness

Uniform interfaces

Page 65: Clojure values

Clojure spiritPragmatism

Correctness

Uniform interfaces

Data over functions

Page 66: Clojure values

Clojure spiritPragmatism

Correctness

Uniform interfaces

Data over functions

Sequences as computation media

Page 67: Clojure values

Clojure spiritPragmatism

Correctness

Uniform interfaces

Data over functions

Sequences as computation media

Reftypes as mutation patterns

Page 68: Clojure values

PragmatismHosted on the JVM

Embrace the host limitations

to be a better guest

Excellent Java interop

Performance over purity

LISP

Page 69: Clojure values

CorrectnessNo silent error

Correct result or failure

Non-negotiable

See 1.2 -> 1.3 numerics changes

Unless the user opts in

Page 70: Clojure values

Uniform interfaces

Page 71: Clojure values

Uniform interfacesWidespread small interfaces

Page 72: Clojure values

Uniform interfacesWidespread small interfaces

Tons of helpers fns built upon

Page 73: Clojure values

Uniform interfacesWidespread small interfaces

Tons of helpers fns built upon

It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.

– Alan Perlis

Page 74: Clojure values

Uniform interfacesWidespread small interfaces

Tons of helpers fns built upon

It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.

– Alan PerlisIt is better to have 100 functions operate on one abstraction than 10 functions on 10 data structures.

– Rich Hickey

Page 75: Clojure values

Uniform interfaces

=> (-> (javax.swing.JFrame.) bean keys sort)(:JMenuBar :accessibleContext :active :alignmentX :alignmentY :alwaysOnTop :alwaysOnTopSupported :background :bufferStrategy :componentCount :components :containerListeners :contentPane :cursorType :defaultCloseOperation ...)

=> (-> {:product-id "ACME123", :description "Powder water"} keys sort)(:description :product-id)

Page 76: Clojure values

Data over functionsLarge reuse of core collection fns

Less specific code

Data go out of the process

Don’t be too clever

A schema is a good API

Page 77: Clojure values

Data over functions

Page 78: Clojure values

Data over functionsHow to enforce invariants

Page 79: Clojure values

Data over functionsHow to enforce invariants

Write a validator function

Page 80: Clojure values

Data over functionsHow to enforce invariants

Write a validator function

Use it in fns pre- and post-conditions

Page 81: Clojure values

Data over functionsHow to enforce invariants

Write a validator function

Use it in fns pre- and post-conditions

Use it in reftypes validators

Page 82: Clojure values

Sequences as pipes

Page 83: Clojure values

Sequences as pipesSequences as ephemeral media of computation

Page 84: Clojure values

Sequences as pipesSequences as ephemeral media of computation

Each stage of a pipeline yields its own seq

Page 85: Clojure values

Sequences as pipesSequences as ephemeral media of computation

Each stage of a pipeline yields its own seq

The ends of the pipeline are not seqs:

Page 86: Clojure values

Sequences as pipesSequences as ephemeral media of computation

Each stage of a pipeline yields its own seq

The ends of the pipeline are not seqs:

db, network, persistent collection etc.

Page 87: Clojure values

Sequences as pipesSequences as ephemeral media of computation

Each stage of a pipeline yields its own seq

The ends of the pipeline are not seqs:

db, network, persistent collection etc.

Page 88: Clojure values

Mutation patterns

Page 89: Clojure values

Mutation patternsReftypes embody mutation patterns

Page 90: Clojure values

Mutation patternsReftypes embody mutation patterns

Application state management:

Page 91: Clojure values

Mutation patternsReftypes embody mutation patterns

Application state management:

Refs, atoms and agents

Page 92: Clojure values

Mutation patternsReftypes embody mutation patterns

Application state management:

Refs, atoms and agents

Program state management:

Page 93: Clojure values

Mutation patternsReftypes embody mutation patterns

Application state management:

Refs, atoms and agents

Program state management:

Vars

Page 94: Clojure values

Mutation patternsReftypes embody mutation patterns

Application state management:

Refs, atoms and agents

Program state management:

Vars

Execution or dataflow management:

Page 95: Clojure values

Mutation patternsReftypes embody mutation patterns

Application state management:

Refs, atoms and agents

Program state management:

Vars

Execution or dataflow management:

Promises, delays and futures

Page 96: Clojure values

How to think functionally?

Page 97: Clojure values

Break your habits

Page 98: Clojure values

Tie your imperative hand behind your back!

Page 99: Clojure values

Tie your OO hand too!

Page 100: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

Mutation

Features

Page 101: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

Mutation

Features

Page 102: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

Mutation

Features

Page 103: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

Mutation

Features

Page 104: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

Mutation

Features

Page 105: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

Mutation

Features

Page 106: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

Mutation

Features

Page 107: Clojure values

Syntax

Core Functional Programming

Recursion and loops

Lazy seqs (creating your owns)

Polymorphism

Types

Macros

Interop

Mutation

Features

Page 108: Clojure values

Pure Functional Programming

without recursion nor loops

without lazy-seq

without indices

Allowed subset

Page 109: Clojure values

Do it until it hurts!(and works)

Page 110: Clojure values

Do it especially for ill-suited problems!

Page 111: Clojure values

Example:Conway’s game of life

Page 112: Clojure values

RulesAt each step in time, the following transitions occur:

• Any live cell with fewer than two live neighbours dies, as if caused by under-population.

• Any live cell with two or three live neighbours lives on to the next generation.

• Any live cell with more than three live neighbours dies, as if by overcrowding.

• Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

(wikipedia)

Page 113: Clojure values

(defn step "Takes a vector of vectors of 0 and 1, and returns the next iteration of the automaton." [board] (let [w (count board) h (count (first board))] (loop [i 0 j 0 new-board board] (cond (>= i w) new-board (>= j h) (recur (inc i) 0 new-board) :else (let [n (neighbours-count board i j) nb (cond (= 3 n) (assoc-in new-board [i j] 1) (not= 2 n) (assoc-in new-board [i j] 0) :else new-board)] (recur i (inc j) new-board))))))

Conway’s game of lifeTypical implementation is full of indices and loops

Page 114: Clojure values

(defn step "Takes a vector of vectors of 0 and 1, and returns the next iteration of the automaton." [board] (let [w (count board) h (count (first board))] (loop [i 0 j 0 new-board board] (cond (>= i w) new-board (>= j h) (recur (inc i) 0 new-board) :else (let [n (neighbours-count board i j) nb (cond (= 3 n) (assoc-in new-board [i j] 1) (not= 2 n) (assoc-in new-board [i j] 0) :else new-board)] (recur i (inc j) new-board))))))

Conway’s game of lifeTypical implementation is full of indices and loops

Page 115: Clojure values

(defn neighbours-count [board i j] (let [i+1 (inc i) j+1 (inc j)] (loop [cnt 0 x (dec i) y (dec j)] (cond (> x i+1) cnt (> y j+1) (recur cnt (inc x) (dec j)) (= [x y] [i j]) (recur cnt x (inc y)) :else (recur (+ cnt (get-in board [x y] 0)) x (inc y))))))

Conway’s game of lifeAnd there’s more!

Page 116: Clojure values

(defn neighbours-count [board i j] (let [i+1 (inc i) j+1 (inc j)] (loop [cnt 0 x (dec i) y (dec j)] (cond (> x i+1) cnt (> y j+1) (recur cnt (inc x) (dec j)) (= [x y] [i j]) (recur cnt x (inc y)) :else (recur (+ cnt (get-in board [x y] 0)) x (inc y))))))

Conway’s game of lifeAnd there’s more!

Page 117: Clojure values

Look, no indicesAt each step in time, the following transitions occur:

• Any live cell with fewer than two live neighbours dies, as if caused by under-population.

• Any live cell with two or three live neighbours lives on to the next generation.

• Any live cell with more than three live neighbours dies, as if by overcrowding.

• Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

(wikipedia)

Page 118: Clojure values

Take a step back!

Page 119: Clojure values

Look, no indicesAt each step in time, the following transitions occur:

• Any live cell with fewer than two live neighbours dies, as if caused by under-population.

• Any live cell with two or three live neighbours lives on to the next generation.

• Any live cell with more than three live neighbours dies, as if by overcrowding.

• Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

(wikipedia)

Page 120: Clojure values

Neighbours!

Page 121: Clojure values

Neighbours!Try to express the rules in code using the neighbours concept

Page 122: Clojure values

Neighbours!Try to express the rules in code using the neighbours concept

Don’t worry about the implementation of neighbours

Page 123: Clojure values

Neighbours!

Page 124: Clojure values

Neighbours!For each living cell or neighbour of a living cell, compute the number of neighbours.

Page 125: Clojure values

Neighbours!For each living cell or neighbour of a living cell, compute the number of neighbours.

Then apply generation rules.

Page 126: Clojure values

Neighbours!

Page 127: Clojure values

Neighbours!Compute all neighbours of the living cells.

Page 128: Clojure values

Neighbours!Compute all neighbours of the living cells.

Occurences count is neighbour count!

Page 129: Clojure values

Neighbours!Compute all neighbours of the living cells.

Occurences count is neighbour count!

Then apply generation rules.

Page 130: Clojure values

(defn step "Takes a set of living cells and returns the next generation (as a set too)." [living-cells] (letfn [(alive [[cell cnt]] (when (or (= cnt 3) (and (= cnt 2) (living-cells cell))) cell))] (->> living-cells (mapcat neighbours) frequencies (keep alive) set)))

Neighbours!

Page 131: Clojure values

(defn step "Takes a set of living cells and returns the next generation (as a set too)." [living-cells] (letfn [(alive [[cell cnt]] (when (or (= cnt 3) (and (= cnt 2) (living-cells cell))) cell))] (->> living-cells (mapcat neighbours) frequencies (keep alive) set)))

Neighbours!

Page 132: Clojure values

(defn step "Takes a set of living cells and returns the next generation (as a set too)." [living-cells] (letfn [(alive [[cell cnt]] (when (or (= cnt 3) (and (= cnt 2) (living-cells cell))) cell))] (->> living-cells (mapcat neighbours) frequencies (keep alive) set)))

Neighbours!(defn neighbours [[x y]] (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])] [(+ x dx) (+ y dy)]))

Page 133: Clojure values

Drafting code

Page 134: Clojure values

Drafting codeDon’t go to the details

Page 135: Clojure values

Drafting codeDon’t go to the details

Draft high-level code you’d like to be able to write to solve the problem

Page 136: Clojure values

Drafting codeDon’t go to the details

Draft high-level code you’d like to be able to write to solve the problem

Try to implement it

Page 137: Clojure values

Drafting codeDon’t go to the details

Draft high-level code you’d like to be able to write to solve the problem

Try to implement it

Negociate between practicality of implementation and draft code

Page 138: Clojure values

But it really hurts...

Page 139: Clojure values

But it really hurts...Ask for help

Page 140: Clojure values

But it really hurts...Ask for help

#clojure on IRC

Page 141: Clojure values

But it really hurts...Ask for help

#clojure on IRC

Stackoverflow

Page 142: Clojure values

But it really hurts...Ask for help

#clojure on IRC

Stackoverflow

clojure google group

Page 143: Clojure values

But it really hurts...Ask for help

#clojure on IRC

Stackoverflow

clojure google group

reach your local user group

Page 144: Clojure values

But it really hurts...Ask for help

#clojure on IRC

Stackoverflow

clojure google group

reach your local user group

create your local user group

Page 145: Clojure values

But it really hurts...Ask for help

#clojure on IRC

Stackoverflow

clojure google group

reach your local user group

create your local user group

mail me [email protected]