SlideShare a Scribd company logo
1 of 52
Alfresco
The Clojure way                                        Carlo Sciolla, Sr R&D Developer at Backbase




ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
public void printAllNames(repo) {
               AuthenticationUtil.runAs(new RunAsWork () {
                 public Object doWork(){
                   for (NodeRef node : getAllNodes(repo)) {
                     String name = getName(node);
                     System.out.println(name);
                   }
                 }
               }, AuthenticationUtil.getAdminUserNAme())
             }


Sample user story
As admin,
I want to loop through all the nodes from the Alfresco repository,
So that I can print their names
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn print-all-names [repo]
               (run-as (admin)
                 (doseq [node (to-seq repo)]
                   (println (property node “cm:name”)))))


                                            #LOC < 1/2




Sample user story
As admin,
I want to loop through all the nodes from the Alfresco repository,
So that I can print their names
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn print-all-names [repo]   Java interop
               (AuthenticationUtil/runAs
                 (reify AuthenticationUtil$RunAsWork
                   (doWork [this]
                     (doseq [node (to-seq repo)]
                       (println (property node “cm:name”)))))
                 (admin)))




How to get there
Having only moved parenthesis around and tweaked it a bit, we
eventually translated our code into Clojure. We still have to get rid of
the anonymous class.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defmacro run-as
               [user f]
               `(let [work# (reify AuthenticationUtil$RunAsWork
                                  (~'doWork [~'this]
                                            ~f))]
                  (AuthenticationUtil/runAs work# ~user)))




Reflection on massive steroids
Macros are “special” functions that, at compile time, shuffle the
pieces they receive in input and return a function. They’re misterious
and powerful: don’t try to decode it now, young jedi.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn print-all-names [repo]
               (run-as (admin)
                 (doseq [node (to-seq repo)]
                   (println (property node “cm:name”)))))




Straight to the point
Clojure, as any Lisp, allows you to easily create clear and concise
DSLs. New functions to enhance expressivity to your programs.
Fewer lines to maintain.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn print-all-names [repo]
               (run-as (admin)
                 (doseq [node (to-seq repo)]
                   (println (property node “cm:name”)))))


                                         https://github.com/skuro/lambdalf




Here be Lambdalf
While Clojure allows direct access to Java classes and instances,
lambdalf provides a more idiomatic access to the core Alfresco API.
You’ll see some examples along the way.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn print-all-names [repo]
               (run-as (admin)
                 (doseq [node (to-seq repo)]
                   (println (property node “cm:name”)))))




Lost In Superfluous Parenthesis?
It is usually perceived that Lisp code has an overwhelming amount of
parenthesis.

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
Parenthesis count




                        VS
                                                          26
                                                          18               24   w/expanded macro




Lost In Superfluous Parenthesis?
It is usually perceived that Lisp code has an overwhelming amount of
parenthesis. It’s usually unfair.

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
the sexp and the city
or: How I learned to stop worrying and love the parens




       ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
sexp = | primitive-elem
                          | list of s-expression




Symbolic Expressions
List based data structures. They may be a nested list of smaller S-
expressions. Best known for their use in Lisp.
                                                           (Wikipedia)
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
Symbols: ns/foo                     Keywords: :key
         odd?                                 ::qualified
         +                                    :ns/qualified
         this!is_a+single*symbol-42           :can+be!weird

Literals: “string”
          c space tab
          42 3.14 42/11 36r16
          true false
          #”^[a-zA-Z]*”
          nil

   Primitive data types
   Basic building blocks. Most of them should look familiar, or meaningful.
   Hopefully.

   ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
list      (c “list” :something)


vector        [“vector” 42 :foobar]


  map {:question “life, universe and everything”
       :answer 42}

   set        #{“foo” 42 :bar}



 Collections or sequences
 All aggregate data types can be encapsulated under the same
 interface: ISeq. Use the powerful Clojure sequence processing library
 to rule them all, but beware: they are all immutable!
 ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
list      (quote (c “list” :something))

   list      ‘(c “list” :something)

             (defn print-all-names [repo]
               (run-as (admin)
                                                function calls
                 (doseq [node (to-seq repo)]
                   (println (property node “cm:name”)))))




LISt Processing
Lists are king among data structures in any Lisp: they also happen to
be code (homoiconicity). Lists are executed by evaluating the first
symbol to a function, then calling it with the others as parameters.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
function definition                    name

             (defn print-all-names [repo]    parameters declaration
               (run-as (admin)
                 (doseq [node (to-seq repo)]
                   (println (property node “cm:name”)))))




Functions
Functional languages needs functions to be first class citizens. In
Clojure, functions can be passed as parameters, put into a collection
or returned as the result of an execution.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
immutability
                     and the art of motorcycle maintenance




ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
Horse horse = new Horse(14);
horse.getPosition();
            ??




                                                                      t

Where is the horse?
The same “thing” such as a variable or an Object, can be completely
different at different moments in time. We call such things identities,
and they relate to a sequence of values.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn move [h]
  {:pos (inc (:pos h))})

(def horse
  {:pos 14})

(:pos horse) ; 14

(move horse) ; {:pos 15}



  Persistent data structures
  All data structures are immutable after their creation. As such, you
  never change them, but rather create new versions of it. We call them
  values, and are effectively easier to handle than Objects.
  ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
Structural sharing
When creating a new version of a value, Clojure runtime optimizes the
process and allows different version of the same data structure to
share parts in memory.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
horse




                                                                        t


                                                       values



Identities and values
Identities refer to a logical sequence of values, which are distinct,
though possibly similar, compound entities. They allow us to bring
time into the picture.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
the seq librabry

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @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.



seq to rule them all
Quite intentionally, you can reduce all Clojure data structures and
Java collections, iterables, Strings and arrays to the very same
interface.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
distinct filter remove for keep keep-indexed cons concat
             lazy-cat mapcat cycle interleave interpose
             rest next fnext nnext drop drop-while nthnext for take
             take-nth take-while butlast drop-last for
             flatten reverse sort sort-by shuffle split-at split-with
             partition partition-all partition-by
             map pmap mapcat for replace reductions map-indexed seque
             first ffirst nfirst second nth when-first
             last rand-nth zipmap into reduce set vec into-array to-
             array-2d frequencies group-by apply
             not-empty some reduce seq? every? not-every? not-any?
             empty? some filter doseq dorun doall seq vals
             keys rseq subseq rsubseq lazy-seq repeatedly iterate
             repeat replicate range line-seq resultset-seq
             re-seq tree-seq file-seq xml-seq iterator-seq
             enumeration-seq


One-stop shop
Dealing with a single abstraction allows for the same functions to be
applicable to an incredible number of problems. The richness of the
seq library is the only swiss army knife you need.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
fully functional

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(map println [“one” “two” “three”])

             (doseq [x [“one” “two” “three”]] (println x))

             (for [x [“one” “two” “three”]] (println x))

             (loop [s [“one” “two” “three”]]
               (println (first s))
                 (if (next s)
                     (recur (rest s))))


Functional looping
Despite being usually a fundamental part of a programming language
course, Clojure doesn’t strictly need any special looping construct,
even if it provides one nonetheless.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn print-all-names [repo]
               (run-as (admin)
                 (doseq [node (to-seq repo)]
                   (println (property node “cm:name”)))))




Sequencing Alfresco
Nodes in Alfresco are stored as a tree. Surely enough, trees can be
represented as nested sequences, allowing for the seq library to
disclose its power.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
distinct filter remove for keep keep-indexed cons concat
             lazy-cat mapcat cycle interleave interpose
             rest next fnext nnext drop drop-while nthnext for take
             take-nth take-while butlast drop-last for
             flatten reverse sort sort-by shuffle split-at split-with
             partition partition-all partition-by
             map pmap mapcat for replace reductions map-indexed seque
             first ffirst nfirst second nth when-first
             last rand-nth zipmap into reduce set vec into-array to-
             array-2d frequencies group-by apply
             not-empty some reduce seq? every? not-every? not-any?
             empty? some filter doseq dorun doall seq vals
             keys rseq subseq rsubseq lazy-seq repeatedly iterate
             repeat replicate range line-seq resultset-seq
             re-seq tree-seq file-seq xml-seq iterator-seq
             enumeration-seq


Depth first traversal
Using the standard seq library, you can compose a linear sequence
out of a tree structure (of nested sequences).

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
clojure.core/tree-seq
             ([branch? children root])
               Returns a lazy sequence of the nodes in a
               tree, via a depth-first walk. branch? must be
               a fn of one arg that returns true if passed a
               node that can have children (but may not).
               children must be a fn of one arg that returns
               a sequence of the children. Will only be
               called on nodes for which branch? returns
               true. root is the root node of the
               tree.


Anatomy of a tree-seq
Functions are first class, and tree-seq is a higher order fn that takes
two functions and a data structure to create a flat sequence.

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
clojure.core/tree-seq
             ([branch? children root])
               Returns a lazy sequence of the nodes in a
               tree, via a depth-first walk. branch? must be
               a fn of one arg that returns true if passed a
               node that can have children (but may not).
               children must be a fn of one arg that returns
               a sequence of the children. Will only be
               called on nodes for which branch? returns
               true. root is the root node of the
               tree.


Thinking Alfresco
Peer to peer associations allow you to create logical trees regardless
of files and folders structure. For the time being, let’s assume we’re
only interested into parent child assocs between nodes.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn type-qname [node]
                                                                   (m/qname (.getType (node-service) (c/c2j node))))
                (defn branch? [node]
                  (qname-isa? (type-qname node)
                              (qname "cm:folder")))
(defn qname-isa? [child parent]
  (.isSubClass (dictionary-service)
               (qname child)                      (defn qname [qname-str]
               (qname parent)))                     (let [[prefix name] (QName/splitPrefixedQName qname-str)]
                                                      (QName/createQName prefix name (namespace-service))))




   First step
   We know that cm:contains is provided as part of cm:folder
   definition. We check that the given node is of a compatible type.
   Lambdalf provides here some Clojure/Java type conversion.
   ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
clojure.core/tree-seq
             ([branch? children root])
               Returns a lazy sequence of the nodes in a
               tree, via a depth-first walk. branch? must be
               a fn of one arg that returns true if passed a
               node that can have children (but may not).
               children must be a fn of one arg that returns
               a sequence of the children. Will only be
               called on nodes for which branch? returns
               true. root is the root node of the
               tree.


Populate the seq
Navigating the tree means getting the children of the traversed node,
if any. This is food for the NodeService.

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn children [node]
               (n/children node)))
                        (defn children [node]
                          (into #{}
                            (doall
                              (map #(c/j2c (.getChildRef %))
                                    (.getChildAssocs (node-service)
                                    (c/c2j node))))))




API bridge
Lambdalf tries to shave the yak for you, and despite its code doesn’t
shine by beauty, it allows for a clean user code. Again, Java and
Clojure interact seamlessly here.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(defn print-all-names [repo] (defn to-seq [node]
               (run-as (admin)             (tree-seq branch? children node))

                 (doseq [node (to-seq repo)]
                   (println (property node “cm:name”)))))




Wrapping it up
Most of the mystery is now gone, the core of print-all-names has been
demystified. While run-as is still magic, it’s easy to tell what’s for.

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
the lord of the repl
  one repl to bring them all and in the lexical scope, bind them




ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
read         R
                                                   user> (defn    Y [r]
eval         E                                            ((fn    [f] (f f))
                                                            (fn   [f]
                                                             (r   (fn [x] ((f f) x))))))
print        P                                     #'user/Y
                                                   user>
loop         L



Almighty shell
It’s common in all Lisp variations development model to have an open
shell to a running environment, called REPL. Here you can define and
test your own code against the running application.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
read         R
                                                   user> (defn    Y [r]
eval         E                                            ((fn    [f] (f f))
                                                            (fn   [f]
                                                             (r   (fn [x] ((f f) x))))))
print        P                                     #'user/Y
                                                   user>
loop         L



Live coding
Similarly to scripted languages, your code is parsed and compiled
into bytecode as soon as you enter it. In facts, you are altering the
current runtime state.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
read         R                                     prompt
                                                   user> (defn Y [r]
eval         E                                            ((fn [f] (f f))
                                                            (fn [f]
                                                             (r (fn [x] ((f f) x))))))
print        P                                     #'user/Y
                                                   user>      result
loop         L



Live coding
Similarly to scripted languages, your code is parsed and compiled
into bytecode as soon as you enter it. In facts, you are altering the
current runtime state.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
+



             $ curl -X POST -u admin:admin 
               http://localhost:8080/alfresco/service/swank
             {port : 4005}

Swank server
Opening a REPL server is just one web script call away. You’ll need a
client to connect, major IDE and editors have one. As usual, Emacs is
superior :-P
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
user> (def folder
                     (a/as-admin
                       (first (s/query "TYPE:"cm:folder""))))
             #'user/folder
             user> (a/as-admin (n/property folder "cm:name"))
             "Sites"
             user>




Baby steps
Being an interactive shell, a REPL allows you to test code step by
step. While it doesn’t free you from the duty of writing tests, it really
helps assessing correctness or feasibility of new ideas.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
Trying it out
We know we should already be able to reduce the Alfresco repository
to a seq, and we can try directly to see if our implementation works as
expected.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
concurrency

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
private HashMap _map = new HashMap();

              public void oneMore(Object k, Object v) {
#fail           _map.put(k, v);
              }




 Shared mutable state
 It’s sometimes desirable to access the same identity from different
 threads. When going concurrent, several tasks that used to be trivial
 are now extremely hard. OO makes it even harder.
 ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
Software Transactional Memory
Similarly to databases, Clojure runtime uses transactions to handle
concurrent access to shared mutable state. Every thread gets the
current value, if changes occur outside, the transaction rolls back.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(def _shared (ref {}))

             (defn update
              [old k v]
               (assoc old k v))

             (defn one-more
              [k v]
               (dosync
                (alter _shared update k v)))


Concurrency IS rocket science
Sorting out concurrency is an extremely difficult task. Clojure provides
language level barriers against poorly designed concurrent access to
shared mutable state.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
sync   coord
             clojure.core/ref
             ([x] [x & options])

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

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



Thereʼs no silver bullet
Different concurrent access patterns require different constructs.
Programmers still have to pay attention to which kind of concurrency
control to use.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
the clojure way

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(map #(property % name) (query “@cm:name:”Sites””))

(defn query
  "Returns all the results of a search"
  ([q]
     (query StoreRef/STORE_REF_WORKSPACE_SPACESSTORE
            SearchService/LANGUAGE_LUCENE q))
  ([store lang q]
     (with-open [rs (.query (search-service) store lang q)]
       (doall (map c/j2c (.getNodeRefs rs))))))

 Warning: alpha code
 Lambdalf and Clojure webscripts have a long way ahead in terms of
 API maturity and usability, but the basic pieces are out there for you to
 start your journey into this new, fancy Lisp.
 ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(write! “new content” node)

(write!
  [^String src node]
  (let [noderef (c/c2j node)
        w (.getWriter (content-service)
                      noderef
                      ContentModel/PROP_CONTENT true)]
    (.putContent w (ByteArrayInputStream.
                     (.getBytes src "UTF-8")))))

 Warning: alpha code
 Lambdalf and Clojure webscripts have a long way ahead in terms of
 API maturity and usability, but the basic pieces are out there for you to
 start your journey into this new, fancy Lisp.
 ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
(to-seq (company-home))

(defn to-seq
  [root]
  (let [user (a/whoami)
         branch? (fn [x] (a/run-as user
                           (m/qname-isa? (n/type-qname x)
                             (m/qname "cm:folder"))))
         children (fn [x] (a/run-as user (n/children x)))]
    (tree-seq branch? children root)))

 Warning: alpha code
 Lambdalf and Clojure webscripts have a long way ahead in terms of
 API maturity and usability, but the basic pieces are out there for you to
 start your journey into this new, fancy Lisp called Clojure.
 ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
John
McCarthy
4 September 1927 - 24 October 2011




      ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
Q/A

ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
Carlo Sciolla
                                                   sr. R&D Developer



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



                          Thank you!
                                                          “A language that doesn't affect the way you think about programming, is not worth knowing”
                                                                                                                                        Alan J. Perlis

About me
Content specialist, Clojurian, biker.
ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro

More Related Content

What's hot

P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)lichtkind
 
Alfresco the clojure way -- Slides from the Alfresco DevCon2011
Alfresco the clojure way -- Slides from the Alfresco DevCon2011Alfresco the clojure way -- Slides from the Alfresco DevCon2011
Alfresco the clojure way -- Slides from the Alfresco DevCon2011Carlo Sciolla
 
Ast transformations
Ast transformationsAst transformations
Ast transformationsHamletDRC
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeCory Forsyth
 
Clojurian Conquest
Clojurian ConquestClojurian Conquest
Clojurian ConquestKent Ohashi
 
AST Transformations
AST TransformationsAST Transformations
AST TransformationsHamletDRC
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!José Paumard
 
Oredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsOredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsAnton Arhipov
 
Mirah Talk for Boulder Ruby Group
Mirah Talk for Boulder Ruby GroupMirah Talk for Boulder Ruby Group
Mirah Talk for Boulder Ruby Groupbaroquebobcat
 
GraphQL API in Clojure
GraphQL API in ClojureGraphQL API in Clojure
GraphQL API in ClojureKent Ohashi
 
Riga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistRiga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistAnton Arhipov
 
JRuby @ Boulder Ruby
JRuby @ Boulder RubyJRuby @ Boulder Ruby
JRuby @ Boulder RubyNick Sieger
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talkJohn Stevenson
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersBartosz Kosarzycki
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring ClojurescriptLuke Donnet
 
LISP: How I Learned To Stop Worrying And Love Parantheses
LISP: How I Learned To Stop Worrying And Love ParanthesesLISP: How I Learned To Stop Worrying And Love Parantheses
LISP: How I Learned To Stop Worrying And Love ParanthesesDominic Graefen
 

What's hot (20)

P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)
 
Alfresco the clojure way -- Slides from the Alfresco DevCon2011
Alfresco the clojure way -- Slides from the Alfresco DevCon2011Alfresco the clojure way -- Slides from the Alfresco DevCon2011
Alfresco the clojure way -- Slides from the Alfresco DevCon2011
 
Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to Come
 
Clojurian Conquest
Clojurian ConquestClojurian Conquest
Clojurian Conquest
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
 
ECMAScript 6
ECMAScript 6ECMAScript 6
ECMAScript 6
 
Dispatch in Clojure
Dispatch in ClojureDispatch in Clojure
Dispatch in Clojure
 
Oredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsOredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java Agents
 
Mirah Talk for Boulder Ruby Group
Mirah Talk for Boulder Ruby GroupMirah Talk for Boulder Ruby Group
Mirah Talk for Boulder Ruby Group
 
GraphQL API in Clojure
GraphQL API in ClojureGraphQL API in Clojure
GraphQL API in Clojure
 
Riga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistRiga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with Javassist
 
JRuby @ Boulder Ruby
JRuby @ Boulder RubyJRuby @ Boulder Ruby
JRuby @ Boulder Ruby
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talk
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
LISP: How I Learned To Stop Worrying And Love Parantheses
LISP: How I Learned To Stop Worrying And Love ParanthesesLISP: How I Learned To Stop Worrying And Love Parantheses
LISP: How I Learned To Stop Worrying And Love Parantheses
 
node ffi
node ffinode ffi
node ffi
 

Similar to Alfresco the clojure way

Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako, Vasil Remeniuk
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationMartin Odersky
 
Scala Days San Francisco
Scala Days San FranciscoScala Days San Francisco
Scala Days San FranciscoMartin Odersky
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John StevensonJAX London
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with ClojureJohn Stevenson
 
Stepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to ScalaStepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to ScalaDerek Chen-Becker
 
Clojure and The Robot Apocalypse
Clojure and The Robot ApocalypseClojure and The Robot Apocalypse
Clojure and The Robot Apocalypseelliando dias
 
Perl programming language
Perl programming languagePerl programming language
Perl programming languageElie Obeid
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaScala Italy
 
Clojure Interoperability
Clojure InteroperabilityClojure Interoperability
Clojure Interoperabilityrik0
 
Hadoop Performance Optimization at Scale, Lessons Learned at Twitter
Hadoop Performance Optimization at Scale, Lessons Learned at TwitterHadoop Performance Optimization at Scale, Lessons Learned at Twitter
Hadoop Performance Optimization at Scale, Lessons Learned at TwitterDataWorks Summit
 
Hadoop Summit 2015: Performance Optimization at Scale, Lessons Learned at Twi...
Hadoop Summit 2015: Performance Optimization at Scale, Lessons Learned at Twi...Hadoop Summit 2015: Performance Optimization at Scale, Lessons Learned at Twi...
Hadoop Summit 2015: Performance Optimization at Scale, Lessons Learned at Twi...Alex Levenson
 
03 introduction to graph databases
03   introduction to graph databases03   introduction to graph databases
03 introduction to graph databasesNeo4j
 
A Brief Introduction to Scala for Java Developers
A Brief Introduction to Scala for Java DevelopersA Brief Introduction to Scala for Java Developers
A Brief Introduction to Scala for Java DevelopersMiles Sabin
 
Miles Sabin Introduction To Scala For Java Developers
Miles Sabin Introduction To Scala For Java DevelopersMiles Sabin Introduction To Scala For Java Developers
Miles Sabin Introduction To Scala For Java DevelopersSkills Matter
 

Similar to Alfresco the clojure way (20)

Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako,
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentation
 
Scala Days San Francisco
Scala Days San FranciscoScala Days San Francisco
Scala Days San Francisco
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with Clojure
 
Scala
ScalaScala
Scala
 
Stepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to ScalaStepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to Scala
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Clojure and The Robot Apocalypse
Clojure and The Robot ApocalypseClojure and The Robot Apocalypse
Clojure and The Robot Apocalypse
 
Perl programming language
Perl programming languagePerl programming language
Perl programming language
 
Clojure
ClojureClojure
Clojure
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of Scala
 
Clojure Interoperability
Clojure InteroperabilityClojure Interoperability
Clojure Interoperability
 
Rakudo
RakudoRakudo
Rakudo
 
Devoxx
DevoxxDevoxx
Devoxx
 
Hadoop Performance Optimization at Scale, Lessons Learned at Twitter
Hadoop Performance Optimization at Scale, Lessons Learned at TwitterHadoop Performance Optimization at Scale, Lessons Learned at Twitter
Hadoop Performance Optimization at Scale, Lessons Learned at Twitter
 
Hadoop Summit 2015: Performance Optimization at Scale, Lessons Learned at Twi...
Hadoop Summit 2015: Performance Optimization at Scale, Lessons Learned at Twi...Hadoop Summit 2015: Performance Optimization at Scale, Lessons Learned at Twi...
Hadoop Summit 2015: Performance Optimization at Scale, Lessons Learned at Twi...
 
03 introduction to graph databases
03   introduction to graph databases03   introduction to graph databases
03 introduction to graph databases
 
A Brief Introduction to Scala for Java Developers
A Brief Introduction to Scala for Java DevelopersA Brief Introduction to Scala for Java Developers
A Brief Introduction to Scala for Java Developers
 
Miles Sabin Introduction To Scala For Java Developers
Miles Sabin Introduction To Scala For Java DevelopersMiles Sabin Introduction To Scala For Java Developers
Miles Sabin Introduction To Scala For Java Developers
 

Recently uploaded

Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 

Recently uploaded (20)

Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 

Alfresco the clojure way

  • 1. Alfresco The Clojure way Carlo Sciolla, Sr R&D Developer at Backbase ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 2. public void printAllNames(repo) { AuthenticationUtil.runAs(new RunAsWork () { public Object doWork(){ for (NodeRef node : getAllNodes(repo)) { String name = getName(node); System.out.println(name); } } }, AuthenticationUtil.getAdminUserNAme()) } Sample user story As admin, I want to loop through all the nodes from the Alfresco repository, So that I can print their names ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 3. (defn print-all-names [repo] (run-as (admin) (doseq [node (to-seq repo)] (println (property node “cm:name”))))) #LOC < 1/2 Sample user story As admin, I want to loop through all the nodes from the Alfresco repository, So that I can print their names ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 4. (defn print-all-names [repo] Java interop (AuthenticationUtil/runAs (reify AuthenticationUtil$RunAsWork (doWork [this] (doseq [node (to-seq repo)] (println (property node “cm:name”))))) (admin))) How to get there Having only moved parenthesis around and tweaked it a bit, we eventually translated our code into Clojure. We still have to get rid of the anonymous class. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 5. (defmacro run-as [user f] `(let [work# (reify AuthenticationUtil$RunAsWork (~'doWork [~'this] ~f))] (AuthenticationUtil/runAs work# ~user))) Reflection on massive steroids Macros are “special” functions that, at compile time, shuffle the pieces they receive in input and return a function. They’re misterious and powerful: don’t try to decode it now, young jedi. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 6. (defn print-all-names [repo] (run-as (admin) (doseq [node (to-seq repo)] (println (property node “cm:name”))))) Straight to the point Clojure, as any Lisp, allows you to easily create clear and concise DSLs. New functions to enhance expressivity to your programs. Fewer lines to maintain. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 7. (defn print-all-names [repo] (run-as (admin) (doseq [node (to-seq repo)] (println (property node “cm:name”))))) https://github.com/skuro/lambdalf Here be Lambdalf While Clojure allows direct access to Java classes and instances, lambdalf provides a more idiomatic access to the core Alfresco API. You’ll see some examples along the way. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 8. (defn print-all-names [repo] (run-as (admin) (doseq [node (to-seq repo)] (println (property node “cm:name”))))) Lost In Superfluous Parenthesis? It is usually perceived that Lisp code has an overwhelming amount of parenthesis. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 9. Parenthesis count VS 26 18 24 w/expanded macro Lost In Superfluous Parenthesis? It is usually perceived that Lisp code has an overwhelming amount of parenthesis. It’s usually unfair. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 10. the sexp and the city or: How I learned to stop worrying and love the parens ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 11. sexp = | primitive-elem | list of s-expression Symbolic Expressions List based data structures. They may be a nested list of smaller S- expressions. Best known for their use in Lisp. (Wikipedia) ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 12. Symbols: ns/foo Keywords: :key odd? ::qualified + :ns/qualified this!is_a+single*symbol-42 :can+be!weird Literals: “string” c space tab 42 3.14 42/11 36r16 true false #”^[a-zA-Z]*” nil Primitive data types Basic building blocks. Most of them should look familiar, or meaningful. Hopefully. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 13. list (c “list” :something) vector [“vector” 42 :foobar] map {:question “life, universe and everything” :answer 42} set #{“foo” 42 :bar} Collections or sequences All aggregate data types can be encapsulated under the same interface: ISeq. Use the powerful Clojure sequence processing library to rule them all, but beware: they are all immutable! ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 14. list (quote (c “list” :something)) list ‘(c “list” :something) (defn print-all-names [repo] (run-as (admin) function calls (doseq [node (to-seq repo)] (println (property node “cm:name”))))) LISt Processing Lists are king among data structures in any Lisp: they also happen to be code (homoiconicity). Lists are executed by evaluating the first symbol to a function, then calling it with the others as parameters. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 15. function definition name (defn print-all-names [repo] parameters declaration (run-as (admin) (doseq [node (to-seq repo)] (println (property node “cm:name”))))) Functions Functional languages needs functions to be first class citizens. In Clojure, functions can be passed as parameters, put into a collection or returned as the result of an execution. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 16. immutability and the art of motorcycle maintenance ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 17. Horse horse = new Horse(14); horse.getPosition(); ?? t Where is the horse? The same “thing” such as a variable or an Object, can be completely different at different moments in time. We call such things identities, and they relate to a sequence of values. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 18. (defn move [h] {:pos (inc (:pos h))}) (def horse {:pos 14}) (:pos horse) ; 14 (move horse) ; {:pos 15} Persistent data structures All data structures are immutable after their creation. As such, you never change them, but rather create new versions of it. We call them values, and are effectively easier to handle than Objects. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 19. Structural sharing When creating a new version of a value, Clojure runtime optimizes the process and allows different version of the same data structure to share parts in memory. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 20. horse t values Identities and values Identities refer to a logical sequence of values, which are distinct, though possibly similar, compound entities. They allow us to bring time into the picture. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 21. the seq librabry ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 22. 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. seq to rule them all Quite intentionally, you can reduce all Clojure data structures and Java collections, iterables, Strings and arrays to the very same interface. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 23. distinct filter remove for keep keep-indexed cons concat lazy-cat mapcat cycle interleave interpose rest next fnext nnext drop drop-while nthnext for take take-nth take-while butlast drop-last for flatten reverse sort sort-by shuffle split-at split-with partition partition-all partition-by map pmap mapcat for replace reductions map-indexed seque first ffirst nfirst second nth when-first last rand-nth zipmap into reduce set vec into-array to- array-2d frequencies group-by apply not-empty some reduce seq? every? not-every? not-any? empty? some filter doseq dorun doall seq vals keys rseq subseq rsubseq lazy-seq repeatedly iterate repeat replicate range line-seq resultset-seq re-seq tree-seq file-seq xml-seq iterator-seq enumeration-seq One-stop shop Dealing with a single abstraction allows for the same functions to be applicable to an incredible number of problems. The richness of the seq library is the only swiss army knife you need. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 24. fully functional ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 25. (map println [“one” “two” “three”]) (doseq [x [“one” “two” “three”]] (println x)) (for [x [“one” “two” “three”]] (println x)) (loop [s [“one” “two” “three”]] (println (first s)) (if (next s) (recur (rest s)))) Functional looping Despite being usually a fundamental part of a programming language course, Clojure doesn’t strictly need any special looping construct, even if it provides one nonetheless. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 26. (defn print-all-names [repo] (run-as (admin) (doseq [node (to-seq repo)] (println (property node “cm:name”))))) Sequencing Alfresco Nodes in Alfresco are stored as a tree. Surely enough, trees can be represented as nested sequences, allowing for the seq library to disclose its power. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 27. distinct filter remove for keep keep-indexed cons concat lazy-cat mapcat cycle interleave interpose rest next fnext nnext drop drop-while nthnext for take take-nth take-while butlast drop-last for flatten reverse sort sort-by shuffle split-at split-with partition partition-all partition-by map pmap mapcat for replace reductions map-indexed seque first ffirst nfirst second nth when-first last rand-nth zipmap into reduce set vec into-array to- array-2d frequencies group-by apply not-empty some reduce seq? every? not-every? not-any? empty? some filter doseq dorun doall seq vals keys rseq subseq rsubseq lazy-seq repeatedly iterate repeat replicate range line-seq resultset-seq re-seq tree-seq file-seq xml-seq iterator-seq enumeration-seq Depth first traversal Using the standard seq library, you can compose a linear sequence out of a tree structure (of nested sequences). ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 28. clojure.core/tree-seq ([branch? children root]) Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. root is the root node of the tree. Anatomy of a tree-seq Functions are first class, and tree-seq is a higher order fn that takes two functions and a data structure to create a flat sequence. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 29. clojure.core/tree-seq ([branch? children root]) Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. root is the root node of the tree. Thinking Alfresco Peer to peer associations allow you to create logical trees regardless of files and folders structure. For the time being, let’s assume we’re only interested into parent child assocs between nodes. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 30. (defn type-qname [node] (m/qname (.getType (node-service) (c/c2j node)))) (defn branch? [node] (qname-isa? (type-qname node) (qname "cm:folder"))) (defn qname-isa? [child parent] (.isSubClass (dictionary-service) (qname child) (defn qname [qname-str] (qname parent))) (let [[prefix name] (QName/splitPrefixedQName qname-str)] (QName/createQName prefix name (namespace-service)))) First step We know that cm:contains is provided as part of cm:folder definition. We check that the given node is of a compatible type. Lambdalf provides here some Clojure/Java type conversion. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 31. clojure.core/tree-seq ([branch? children root]) Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. root is the root node of the tree. Populate the seq Navigating the tree means getting the children of the traversed node, if any. This is food for the NodeService. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 32. (defn children [node] (n/children node))) (defn children [node] (into #{} (doall (map #(c/j2c (.getChildRef %)) (.getChildAssocs (node-service) (c/c2j node)))))) API bridge Lambdalf tries to shave the yak for you, and despite its code doesn’t shine by beauty, it allows for a clean user code. Again, Java and Clojure interact seamlessly here. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 33. (defn print-all-names [repo] (defn to-seq [node] (run-as (admin) (tree-seq branch? children node)) (doseq [node (to-seq repo)] (println (property node “cm:name”))))) Wrapping it up Most of the mystery is now gone, the core of print-all-names has been demystified. While run-as is still magic, it’s easy to tell what’s for. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 34. the lord of the repl one repl to bring them all and in the lexical scope, bind them ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 35. read R user> (defn Y [r] eval E ((fn [f] (f f)) (fn [f] (r (fn [x] ((f f) x)))))) print P #'user/Y user> loop L Almighty shell It’s common in all Lisp variations development model to have an open shell to a running environment, called REPL. Here you can define and test your own code against the running application. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 36. read R user> (defn Y [r] eval E ((fn [f] (f f)) (fn [f] (r (fn [x] ((f f) x)))))) print P #'user/Y user> loop L Live coding Similarly to scripted languages, your code is parsed and compiled into bytecode as soon as you enter it. In facts, you are altering the current runtime state. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 37. read R prompt user> (defn Y [r] eval E ((fn [f] (f f)) (fn [f] (r (fn [x] ((f f) x)))))) print P #'user/Y user> result loop L Live coding Similarly to scripted languages, your code is parsed and compiled into bytecode as soon as you enter it. In facts, you are altering the current runtime state. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 38. + $ curl -X POST -u admin:admin http://localhost:8080/alfresco/service/swank {port : 4005} Swank server Opening a REPL server is just one web script call away. You’ll need a client to connect, major IDE and editors have one. As usual, Emacs is superior :-P ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 39. user> (def folder (a/as-admin (first (s/query "TYPE:"cm:folder"")))) #'user/folder user> (a/as-admin (n/property folder "cm:name")) "Sites" user> Baby steps Being an interactive shell, a REPL allows you to test code step by step. While it doesn’t free you from the duty of writing tests, it really helps assessing correctness or feasibility of new ideas. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 40. Trying it out We know we should already be able to reduce the Alfresco repository to a seq, and we can try directly to see if our implementation works as expected. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 41. concurrency ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 42. private HashMap _map = new HashMap(); public void oneMore(Object k, Object v) { #fail _map.put(k, v); } Shared mutable state It’s sometimes desirable to access the same identity from different threads. When going concurrent, several tasks that used to be trivial are now extremely hard. OO makes it even harder. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 43. Software Transactional Memory Similarly to databases, Clojure runtime uses transactions to handle concurrent access to shared mutable state. Every thread gets the current value, if changes occur outside, the transaction rolls back. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 44. (def _shared (ref {})) (defn update [old k v] (assoc old k v)) (defn one-more [k v] (dosync (alter _shared update k v))) Concurrency IS rocket science Sorting out concurrency is an extremely difficult task. Clojure provides language level barriers against poorly designed concurrent access to shared mutable state. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 45. sync coord clojure.core/ref ([x] [x & options]) clojure.core/atom ([x] [x & options]) clojure.core/agent ([state & options]) Thereʼs no silver bullet Different concurrent access patterns require different constructs. Programmers still have to pay attention to which kind of concurrency control to use. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 46. the clojure way ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 47. (map #(property % name) (query “@cm:name:”Sites””)) (defn query "Returns all the results of a search" ([q] (query StoreRef/STORE_REF_WORKSPACE_SPACESSTORE SearchService/LANGUAGE_LUCENE q)) ([store lang q] (with-open [rs (.query (search-service) store lang q)] (doall (map c/j2c (.getNodeRefs rs)))))) Warning: alpha code Lambdalf and Clojure webscripts have a long way ahead in terms of API maturity and usability, but the basic pieces are out there for you to start your journey into this new, fancy Lisp. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 48. (write! “new content” node) (write! [^String src node] (let [noderef (c/c2j node) w (.getWriter (content-service) noderef ContentModel/PROP_CONTENT true)] (.putContent w (ByteArrayInputStream. (.getBytes src "UTF-8"))))) Warning: alpha code Lambdalf and Clojure webscripts have a long way ahead in terms of API maturity and usability, but the basic pieces are out there for you to start your journey into this new, fancy Lisp. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 49. (to-seq (company-home)) (defn to-seq [root] (let [user (a/whoami) branch? (fn [x] (a/run-as user (m/qname-isa? (n/type-qname x) (m/qname "cm:folder")))) children (fn [x] (a/run-as user (n/children x)))] (tree-seq branch? children root))) Warning: alpha code Lambdalf and Clojure webscripts have a long way ahead in terms of API maturity and usability, but the basic pieces are out there for you to start your journey into this new, fancy Lisp called Clojure. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 50. John McCarthy 4 September 1927 - 24 October 2011 ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 51. Q/A ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro
  • 52. Carlo Sciolla sr. R&D Developer http://skuro.tk @skuro http://backbase.com Thank you! “A language that doesn't affect the way you think about programming, is not worth knowing” Alan J. Perlis About me Content specialist, Clojurian, biker. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro

Editor's Notes

  1. Hi all, my name is Carlo, and I&amp;#x2019;m here to show you LISP\n- how many know about FP?\n- how many know about Lisp?\n- how many about Clojure?\n&lt;Intro to Lisp?&gt;\nBefore blowing your mind away with some good Clojure code, let&amp;#x2019;s start from a familiar Java snippet\n
  2. Simple use case: print the name property of all the nodes in the repository.\n10 lines of code, pretty straightforward. What&amp;#x2019;s wrong with it?\nrunAsAdmin is taking two lines\nRunAsWord and doWork are incidental complexity, not part of the core business logic but just a necessary overhead Java forces us to use.\nLet&amp;#x2019;s start translating this code into Clojure to see if we can get around it.\n
  3. The logic flow still resembles 1-to-1 the Java code we saw in the previous slide. Lisp first timers might not be able to actually parse this code, but the general idea should be clear.\nSignal to noise ratio is at a minimum, most of the code directly implements the business logic, with little language overhead.\nI&amp;#x2019;m going to use this very small piece of Clojure in several slides, so don&amp;#x2019;t worry if you can&amp;#x2019;t fully understand all the details now.\n#LOC are now reduced to less than a half, while still preserving the data flow. \nIn order to start understanding how this works, a little step back to disclose the magic behind run-as.\n
  4. This is a line-by-line working Clojure code doing exactly the same things we coded in Java before. \nWe still have all the complexity of instantiating an anonymous class (via reify), we just removed some lines of code and added Clojure noise around. But now we&amp;#x2019;re into Lisp territories, and we can make a step further. \n
  5. We&amp;#x2019;re definitely going ahead of ourselves here: I&amp;#x2019;m showing this to you just for the sake of completeness. For now, just regard run-as as a function, that allows for its arguments to be evaluated in a special way. We&amp;#x2019;ll learn a bit more on macros later on. For now, let&amp;#x2019;s see how this macro will help us cutting the previous code.\n
  6. Most often than not, when you write less code for the same piece of logic, you&amp;#x2019;re helping making the world a better place.\nClojure inherits from Lisp an incredible expressivity power that results in high density concise code.\n\n
  7. run-as, and some other things you can see in this code are included in Lambdalf, an adapter library that allows you to write idiomatic Clojure code against the Alfresco foundation API.\nWhile Clojure code can directly access Java classes and methods, it&amp;#x2019;s often convenient to wrap the heavy lifting in a library call. It&amp;#x2019;s open source, go and have a look.\nEven without extensive knowledge of lambdalf, it should be now a bit more clear how this code works. Before going deeper into the details, let&amp;#x2019;s demystify a common misconception. How many of you are disturbed by the parenthesis?\n
  8. Let&amp;#x2019;s count them: 18\nThey indeed seem a lot, especially that bunch at the end of the listing. Can you guess how many parenthesis the Java implementation used?\n
  9. Clojure wins the contest with a third parenthesis cut. Even the macro expanded code, Clojure lets you type less parenthesis. As a final comment, when you use a decent LISP editor, say Emacs, most of the times you only type open parenthesis, leaving the IDE the task to close them where appropriate.\nNow that we had a glimpse of how Clojure can ease your life as a developer, we can move on and give the language a closer look.\n
  10. Sexp stands for symbolic expression. The term is used to describe data structures formed by nested lists. Let&amp;#x2019;s start with a formal definition for a s-exp.\n\n
  11. Given this simple description, we think of simple examples for sexps:\n- a string\n- a list of strings\n- a list containing one string and a list of strings\nIn Clojure there are a number of primitive types that can appear in symbolic expressions.\n
  12. Simple tokens in a symbolic expression can be one of the types shown here. Symbols are identifiers that evaluate to something else, like a function or in general to a variable. There are a number of different literal forms to express values in primitive types, such as Strings, numbers or regular expressions. For numbers, Clojure allows you to express ratios, with no precision loss, numbers with a radix other than 10 and only uses 64bit precision Java primitive types whenever a conversion is needed (long, double). Nil is the same as Java null, and evaluates to a falsy value in boolean tests. Probably the oddest part of this slide is represented by other that guy over there, or by the keywords. Keywords are a special Clojure type that always evaluate to themselves. They&amp;#x2019;re normally used as keys in maps, which we are going to introduce in the next slide.\n
  13. These are literals for aggregated data types you can use to host a number of values. They retain the normal semantic of the same types in other programming languages, as per ordering and performance constraints. There are two main points about aggregate data types that must be made clear:\n- what you are looking at are literals, which means they&amp;#x2019;re values. As you cannot tell the number 1 to change itself to be number 2, you cannot as a list to add a new value. All values are immutable, and the same goes for collections in Clojure. If you don&amp;#x2019;t have a background in functional programming, this might look like shooting on your feet. It turns out to be great\n- in the Clojure internals, there&amp;#x2019;s an interface called ISeq which represents a sequence, and which is used by virtually each and every clojure API ever written. All collections can be turned in sequences.\n
  14. Lists deserve a special mention in every Lisp, as they are also the main component of the language itself. In facts, Clojure code is made up of lists, with the convention that the first element of a list is treated as a symbol that must resolve to a function. Such a function is then called with all the other elements in the list passed as parameters. In order to avoid plain lists that do not represent code from being evaluated, there&amp;#x2019;s a special function, called quote, which can also be expressed as a single quote preceding the list.\nThe very fact that Clojure code is also a Clojure data structure allows for incredible meta programming power, with macros that can consume plain clojure code, and cut, squeeze or reassemble it to produce something completely new at runtime. It forces the language itself to be extremely consistent with itself, with just a little syntax.\n
  15. As we&amp;#x2019;re no more in the object oriented world, there&amp;#x2019;s nothing special that a function requires before it can be declared, apart from a namespace.\nOnce this code is compiled, `print-all-names` symbol is bound within the current namespace to a function that accepts one parameter. We&amp;#x2019;re also in a dynamically typed language, and this results in input parameters and return values to have no compile time types.\nNow we know how to create functions, which take parameters and do something with them. But there&amp;#x2019;s something that \n
  16. The market is changing\n\nFinancials are not longer controlling the money.\n\nWe are moving more and more to a customer controlled market.\n\n
  17. Another way to see it is to compare (= horseA horseB) and (.equals horseA horseB)\n
  18. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  19. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  20. \n
  21. The market is changing\n\nFinancials are not longer controlling the money.\n\nWe are moving more and more to a customer controlled market.\n\n
  22. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  23. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  24. The market is changing\n\nFinancials are not longer controlling the money.\n\nWe are moving more and more to a customer controlled market.\n\n
  25. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  26. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  27. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  28. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  29. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  30. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  31. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  32. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  33. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  34. The market is changing\n\nFinancials are not longer controlling the money.\n\nWe are moving more and more to a customer controlled market.\n\n
  35. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  36. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  37. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  38. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  39. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  40. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  41. The market is changing\n\nFinancials are not longer controlling the money.\n\nWe are moving more and more to a customer controlled market.\n\n
  42. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  43. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  44. Transactions are quite different than locks in that they allow for composability: you can throw in any ref you want, while locking must always be consistent when protecting the same Object\n
  45. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  46. The market is changing\n\nFinancials are not longer controlling the money.\n\nWe are moving more and more to a customer controlled market.\n\n
  47. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  48. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  49. This is because new banks are taking over and winning customers.\n\nExample: BankSimple - reinventing personal banking.\n\nThey start with a clean slate; no legacy, no branches to support.\n\nA pure customer focussed, mobile and internet oriented bank is shaking up the retail banking space in North America.\n
  50. The market is changing\n\nFinancials are not longer controlling the money.\n\nWe are moving more and more to a customer controlled market.\n\n
  51. The market is changing\n\nFinancials are not longer controlling the money.\n\nWe are moving more and more to a customer controlled market.\n\n
  52. Branches and ATM&amp;#x2019;s should no longer be the main focus areas for banks.\n\nOnline, Mobile &amp; Social Banking combined with Customer Experience &amp; Trust are becoming key.\n