Date post: | 10-May-2015 |
Category: |
Technology |
Upload: | carlo-sciolla |
View: | 1,410 times |
Download: | 2 times |
A DIVE INTO CLOJURE | April 6, 2012 | @skuro
Carlo Sciolla, Product Lead @ BackbaseA dive into Clojure
Friday, April 6, 2012
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
A DIVE INTO CLOJURE | April 6, 2012 | @skuro
Motivationala.k.a. the towel they forgot to bring
Friday, April 6, 2012
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
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
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
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
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
A DIVE INTO CLOJURE | April 6, 2012 | @skuro
Open the parensto never look at programs the same way
Friday, April 6, 2012
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
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
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
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
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
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
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
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
Friday, April 6, 2012
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
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
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
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
A DIVE INTO CLOJURE | April 6, 2012 | @skuro
‘cause Java beans give you gasImmutability
Friday, April 6, 2012
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
A DIVE INTO CLOJURE | April 6, 2012 | @skuro
let your code write itselfMacro advantage
Friday, April 6, 2012
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
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
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
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
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
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
A DIVE INTO CLOJURE | April 6, 2012 | @skuro
when you ain’t gonna need it allLazy as a sloth
Friday, April 6, 2012
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
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
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
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
A DIVE INTO CLOJURE | April 6, 2012 | @skuro
Whatʼs next
Friday, April 6, 2012
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
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
A DIVE INTO CLOJURE | April 6, 2012 | @skuro
Q/A
Friday, April 6, 2012
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