a dive into clojure

54
A DIVE INTO CLOJURE | April 6, 2012 | @skuro Carlo Sciolla, Product Lead @ Backbase A dive into Clojure Friday, April 6, 2012

Upload: carlo-sciolla

Post on 10-May-2015

1.418 views

Category:

Technology


2 download

DESCRIPTION

This presentation was given at the April Tech Meeting hosted by Orange11 (@orange11hq)

TRANSCRIPT

Page 1: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Carlo Sciolla, Product Lead @ BackbaseA dive into Clojure

Friday, April 6, 2012

Page 2: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

About meNext gen portal software for the Bank 2.0, a recent history of Alfresco and ECM specialist, Meetup organizer.

Amsterdam Clojurians

http://www.backbase.com http://bit.ly/amsclj

Carlo Sciolla

http://skuro.tk@skuro

Product Lead

Friday, April 6, 2012

Page 3: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Motivationala.k.a. the towel they forgot to bring

Friday, April 6, 2012

Page 4: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuroA DIVE INTO CLOJURE | April 6, 2012 | @skuro

I've seen things you people wouldn't believeProgramming languages evolved throughout half a century. Paradigms rose and faded, with OOP and Java™ now the de-facto standards. Yet there’s more to programming than what objects have to offer.

Friday, April 6, 2012

Page 5: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuroA DIVE INTO CLOJURE | April 6, 2012 | @skuro

The standard packageThere are a number of design choices behind the Java™ programming languages, and the ecosystem around it, that are quickly taken for granted. This effectively creates a horizon that can limit your sight.

* Single inheritance* [Almost] everything is an Object* Single dispatch* Non-covariant generics* Type erasures* C-like syntax* Frameworks composition

Friday, April 6, 2012

Page 6: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuroA DIVE INTO CLOJURE | April 6, 2012 | @skuro

A paradigm shiftAs much as they’ve disappeared from mainstream development, they’re now regaining momentum. Functional languages such as Scala and Clojure are getting the spots on.

f (x)Friday, April 6, 2012

Page 7: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

?The rocky road to LISPThere are more than fifty years of history behind any modern Lisp, and while most of them have greatly influenced other languages, there’s a unique core bulk of concepts that only finds home in a Lisp.

cons

gensym trampoline

lambda

macro

recur

let

monad

zipper

seq

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Friday, April 6, 2012

Page 8: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

“”A DIVE INTO CLOJURE | April 6, 2012 | @skuro

When you finally get itThe very idea that you have to get Lisp is fascinating. As a matter of facts, every Lisp developer experienced a moment of illumination, after which all those parens finally fit together.

Lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days

Eric S. Raymond

Friday, April 6, 2012

Page 9: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Open the parensto never look at programs the same way

Friday, April 6, 2012

Page 10: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Double rainbowsAs much as it might seem gibberish at first sight, at its very core there’s little to know about Lisp syntax. Clojure adds some syntactic sugar on top of standard Lisp, but the basics are all there.

(defn hello [name] (println (str “Hello, ” name “!”)))

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Friday, April 6, 2012

Page 11: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Function callsThe first symbol after an open parenthesis is interpreted as the name of the function to call, with all the other members passed as parameters.

function calls

(defn hello [name] (println (str “Hello, ” name “!”)))

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Friday, April 6, 2012

Page 12: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Evaluation strategy

(defn hello [name] (println (str “Hello, ” name “!”)))

user> (hello “World”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Friday, April 6, 2012

Page 13: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Evaluation strategyVariables binding follow lexicographical order.

(defn hello [name] (println (str “Hello, ” name “!”)))

user> (hello “World”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Friday, April 6, 2012

Page 14: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

first invocation

(defn hello [name] (println (str “Hello, ” name “!”)))

user> (hello “World”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Evaluation strategyVariables binding follows lexicographical order. Then start from the innermost list.

Friday, April 6, 2012

Page 15: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

second invocation

(defn hello [name] (println “Hello, World!”))

user> (hello “World”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Evaluation strategyVariables binding follows lexicographical order. Then start from the innermost list. Substitute it with its yielded value, then repeat.

Friday, April 6, 2012

Page 16: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

done

(defn hello [name] nil)

user> (hello “World”)Hello, World!

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Evaluation strategyVariables binding follows lexicographical order. Then start from the innermost list. Substitute it with its yielded value, then repeat. When we have a single value, we’re done and can yield a result.

Friday, April 6, 2012

Page 17: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

user> (hello “World”)Hello, World!niluser>

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Read, Eval, Print LoopYou just saw the REPL in action. More than a simple function execution tool, it’s

Read

Eval

Print

Friday, April 6, 2012

Page 18: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

by any other interface it wouldn’t smell the sameWhatʼs in a seq

Friday, April 6, 2012

Page 19: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Much more than a collectionA sequential access data structure, most of the Clojure standard library functions are able to process a sequence.

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

clojure.core/seq([coll]) Returns a seq on the collection. If the collection is empty, returns nil. (seq nil) returns nil. seq also works on Strings, native Java arrays (of reference types) and any objects that implement Iterable.

Friday, April 6, 2012

Page 20: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(seq '(1 "test" :odd true)) => (1 "test" :odd true)(seq [1 "test" :odd true]) => (1 "test" :odd true)(seq {1 "test" :odd true}) => ([1 "test"] [:odd true])(seq #{1 "test" :odd true}) => (1 :odd true "test")(seq “test”) => (\t \e \s \t)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

More than a collectionA sequential access data structure, most of the Clojure standard library functions are able to process a sequence. Wrapping a collection in a sequence is just one function call away.

Friday, April 6, 2012

Page 21: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Automatic conversionYou don’t even have to bother converting your data structure, as the standard library will do that for you.

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(map identity [1 2 3 4]) ; (1 2 3 4)(filter odd? ‘(1 2 3 4)) ; (1 3)(reduce str “test”) ; “test”

Friday, April 6, 2012

Page 22: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

‘cause Java beans give you gasImmutability

Friday, April 6, 2012

Page 23: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

On state and identityWhen using a POJO to model an identity, you fail to keep time into consideration. Mutable state makes it hard to reason about code execution in a concurrent environment.

t

??

Horse horse = new Horse(14);horse.getPosition();

Friday, April 6, 2012

Page 24: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Persistent data structuresIn Clojure, data structures are immutable. There’s no “add to map”, you rather have to create a new map from the previous one, plus one element.

(let [x {:one 1}] (assoc x :two 2) (println x) ; {:one 1} (println (assoc x :two 2))) ; {:one 1 :two 2}

Friday, April 6, 2012

Page 25: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

(defn letter-count [string] (let [reduce-fn (fn [counts letter] (let [count (or (counts letter) 0)] (assoc counts letter (inc count))))] (reduce reduce-fn {} string)))

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Friday, April 6, 2012

Page 26: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 27: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 28: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 29: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)(reduce-fn {\A 1 \m 1} \s)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 30: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)(reduce-fn {\A 1 \m 1} \s)(reduce-fn {\A 1 \m 1 \s 1} \t)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 31: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)(reduce-fn {\A 1 \m 1} \s)(reduce-fn {\A 1 \m 1 \s 1} \t)(reduce-fn {\A 1 \m 1 \s 1 \t 1} \e)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 32: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)(reduce-fn {\A 1 \m 1} \s)(reduce-fn {\A 1 \m 1 \s 1} \t)(reduce-fn {\A 1 \m 1 \s 1 \t 1} \e)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1} \r)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 33: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)(reduce-fn {\A 1 \m 1} \s)(reduce-fn {\A 1 \m 1 \s 1} \t)(reduce-fn {\A 1 \m 1 \s 1 \t 1} \e)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1} \r)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1} \d)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 34: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)(reduce-fn {\A 1 \m 1} \s)(reduce-fn {\A 1 \m 1 \s 1} \t)(reduce-fn {\A 1 \m 1 \s 1 \t 1} \e)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1} \r)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1} \d)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1 \d 1} \a)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 35: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)(reduce-fn {\A 1 \m 1} \s)(reduce-fn {\A 1 \m 1 \s 1} \t)(reduce-fn {\A 1 \m 1 \s 1 \t 1} \e)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1} \r)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1} \d)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1 \d 1} \a)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1 \d 1 \a 1} \m)

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 36: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

(reduce-fn {} \A)(reduce-fn {\A 1} \m)(reduce-fn {\A 1 \m 1} \s)(reduce-fn {\A 1 \m 1 \s 1} \t)(reduce-fn {\A 1 \m 1 \s 1 \t 1} \e)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1} \r)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1} \d)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1 \d 1} \a)(reduce-fn {\A 1 \m 1 \s 1 \t 1 \e 1 \r 1 \d 1 \a 1} \m){\A 1 \m 2 \s 1 \t 1 \e 1 \r 1 \d 1 \a 1}

user> (letter-count “Amsterdam”)

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Doing real workImmutability doesn’t get in the way of solving programming problems. If anything, it makes it easier to reason about execution!

Friday, April 6, 2012

Page 37: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuroA DIVE INTO CLOJURE | April 6, 2012 | @skuro

Software transactional memoryWhen shared mutable state is really required, Clojure offers a number of constructs to handle it in a inherently thread safe manner, which frees you from resource locking.

clojure.core/ref([x] [x & options])

clojure.core/atom([x] [x & options])

clojure.core/agent([state & options])

sync coord

Friday, April 6, 2012

Page 38: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

let your code write itselfMacro advantage

Friday, April 6, 2012

Page 39: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

The classic exampleCan you tell what’s wrong with this code?

(defn unless “Executes body only if pred is false” [pred body] (if (not pred) body)

(unless (odd? 11) (println “woot?”))(unless (odd? 12) (println “woot?”))

user code

Friday, April 6, 2012

Page 40: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Eager evaluation kills itWhen implementing unless as a function, its arguments are evaluated before unless itself is executed. This effectively prevents you from getting it right.

(unless (odd? 11) (println “woot?”))=> “woot?”

(unless (odd? 12) (println “woot?”))=> “woot?”

Friday, April 6, 2012

Page 41: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Macros FTWMacros look like functions, but are treated in a slightly different way: their arguments are passed unevaluated, and they’re supposed to return code!

(defmacro unless [pred body] (list 'if (list 'not pred) body))

Friday, April 6, 2012

Page 42: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Reflection on steroidsYou can inspect your macro with macroexpand and macroexpand-1. The result now looks good: treating code as data, we can shuffle all the pieces and put them in the order we want. This is LISP.

(macroexpand '(unless (odd? 12) (println "woot?")))

(if (not (odd? 12)) (println "woot?"))

=>

Friday, April 6, 2012

Page 43: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Syntactic sugarThe syntax quote reader macro helps you write macros, as you end up writing a “template” for the code you want to generate.

(defmacro unless [pred body] `(if (not ~pred) ~body))

Friday, April 6, 2012

Page 44: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Programmable programming languageMacros are a powerful tool, and with great power comes great responsibility: use with care. That said, macros alone puts the whole concept of DSL just a built in of the language.

; automatic resource freeing(with-open [f (java.io.FileInputStream. "foo.txt")] (loop [c (.read f)] (when (not (= -1 c)) (println (char c)) (recur (.read f)))))

; threading macro(-> c char println)

Friday, April 6, 2012

Page 45: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

when you ain’t gonna need it allLazy as a sloth

Friday, April 6, 2012

Page 46: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Infinite sequencesIn presence of strict (eager) evaluation, a collection of infinite elements will blow up your heap.

List<Integer> allInts = new ArrayList<Integer>();for (Integer i = 0; ; ++i) { allInts.add(i);}

Friday, April 6, 2012

Page 47: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Lazy sequences to the rescueA call to lazy-seq will put evaluation on hold, so that only the requested elements are “realized”. Also on the plus side, if you don’t hold a reference on the head the unused elements are garbage collected!

(defn all-ints [from] (cons from (lazy-seq (all-ints (inc from)))))

(take 10 (all-ints 0))=> (0 1 2 3 4 5 6 7 8 9)

Friday, April 6, 2012

Page 48: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

The upsides and the flipsideMost of the Clojure sequence library is made of lazy functions. While this is handy in most cases, you must be aware of what’s lazy in your code, as you might have to force the full realization of a seq.

(with-open [session (hibernate-session)] (let [names [“carlo” “thomas” “luca” “nol”] results (map #(find-user % session) names)] (reset! users results))

(take 1 @users) ; org.hibernate.SessionException: Session was already closed

Friday, April 6, 2012

Page 49: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

The programmer in controlYou can choose whether is nice to have a lazy sequence, and when it’s best to have all the elements available at once.

user=> (doc doall)-------------------------clojure.core/doall([coll] [n coll]) When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time.

Friday, April 6, 2012

Page 50: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Whatʼs next

Friday, April 6, 2012

Page 51: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Some drops in the seaDespite being so young a language, the Clojure ecosystem is already huge. These are only a few ideas on where to start if you want to learn more about Clojure.

* http://clojure.org* ClojureScript* Overtone* core-logic

* http://4clojure.com* #clojure on Freenode

Friday, April 6, 2012

Page 52: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Always open for businessIn two and a half year, we never missed a meetup. Come along and enjoy the Dutch Clojure community!

Amsterdam Clojurians

http://bit.ly/amsclj

April 18th

hosted by:

Friday, April 6, 2012

Page 53: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuro

Q/A

Friday, April 6, 2012

Page 54: A Dive Into Clojure

A DIVE INTO CLOJURE | April 6, 2012 | @skuroA DIVE INTO CLOJURE | April 6, 2012 | @skuro

Thanks @skuro http://skuro.tk http://www.backbase.com

http://imgs.xkcd.com/comics/lisp.jpg

Friday, April 6, 2012