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

Friday, November 4, 2011
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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
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

Friday, November 4, 2011
the sexp and the city
                   or: How I learned to stop worrying and love the parens




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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
immutability
                                                and the art of motorcycle maintenance




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

Friday, November 4, 2011
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

Friday, November 4, 2011
(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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
the seq librabry

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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
fully functional

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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
(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

Friday, November 4, 2011
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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
+



                                        $ 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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
concurrency

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

Friday, November 4, 2011
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

Friday, November 4, 2011
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

Friday, November 4, 2011
(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

Friday, November 4, 2011
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

Friday, November 4, 2011
the clojure way

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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
(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

Friday, November 4, 2011
John
       McCarthy
       4 September 1927 - 24 October 2011




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

Friday, November 4, 2011
Q/A

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

Friday, November 4, 2011
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

Friday, November 4, 2011

More Related Content

What's hot

ES6 in Production [JSConfUY2015]
ES6 in Production [JSConfUY2015]ES6 in Production [JSConfUY2015]
ES6 in Production [JSConfUY2015]Guillermo Paz
 
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
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!José Paumard
 
Introduction to Scala for Java Developers
Introduction to Scala for Java DevelopersIntroduction to Scala for Java Developers
Introduction to Scala for Java DevelopersMichael Galpin
 
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
 
Clojurian Conquest
Clojurian ConquestClojurian Conquest
Clojurian ConquestKent Ohashi
 
Oredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsOredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsAnton Arhipov
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is hereSebastiano Armeli
 
How Functions Work
How Functions WorkHow Functions Work
How Functions WorkSaumil Shah
 
JRuby @ Boulder Ruby
JRuby @ Boulder RubyJRuby @ Boulder Ruby
JRuby @ Boulder RubyNick Sieger
 
GraphQL API in Clojure
GraphQL API in ClojureGraphQL API in Clojure
GraphQL API in ClojureKent Ohashi
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
JavaOne 2015 - Having fun with Javassist
JavaOne 2015 - Having fun with JavassistJavaOne 2015 - Having fun with Javassist
JavaOne 2015 - Having fun with JavassistAnton Arhipov
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring ClojurescriptLuke Donnet
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPGuilherme Blanco
 

What's hot (20)

Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
 
ES6 in Production [JSConfUY2015]
ES6 in Production [JSConfUY2015]ES6 in Production [JSConfUY2015]
ES6 in Production [JSConfUY2015]
 
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
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
 
Dispatch in Clojure
Dispatch in ClojureDispatch in Clojure
Dispatch in Clojure
 
Introduction to Scala for Java Developers
Introduction to Scala for Java DevelopersIntroduction to Scala for Java Developers
Introduction to Scala for Java Developers
 
Shell script-sec
Shell script-secShell script-sec
Shell script-sec
 
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
 
Clojurian Conquest
Clojurian ConquestClojurian Conquest
Clojurian Conquest
 
Oredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsOredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java Agents
 
ECMAScript 6
ECMAScript 6ECMAScript 6
ECMAScript 6
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
 
How Functions Work
How Functions WorkHow Functions Work
How Functions Work
 
JRuby @ Boulder Ruby
JRuby @ Boulder RubyJRuby @ Boulder Ruby
JRuby @ Boulder Ruby
 
GraphQL API in Clojure
GraphQL API in ClojureGraphQL API in Clojure
GraphQL API in Clojure
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
JavaOne 2015 - Having fun with Javassist
JavaOne 2015 - Having fun with JavassistJavaOne 2015 - Having fun with Javassist
JavaOne 2015 - Having fun with Javassist
 
Unix shell scripts
Unix shell scriptsUnix shell scripts
Unix shell scripts
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
 

Viewers also liked

Jetlag credentials
Jetlag credentialsJetlag credentials
Jetlag credentialsJETLAG
 
Presentation1
Presentation1Presentation1
Presentation1KPM
 
Presentation1
Presentation1Presentation1
Presentation1KPM
 
קורס רשתות חברתיות עבור המי&quot;ל חבר
קורס רשתות חברתיות עבור המי&quot;ל חברקורס רשתות חברתיות עבור המי&quot;ל חבר
קורס רשתות חברתיות עבור המי&quot;ל חברAnnie Dudkiewicz
 
Brochure Datametrie
Brochure DatametrieBrochure Datametrie
Brochure DatametrieJETLAG
 
Presentation 3
Presentation 3Presentation 3
Presentation 3KPM
 
Presentation2
Presentation2Presentation2
Presentation2KPM
 

Viewers also liked (7)

Jetlag credentials
Jetlag credentialsJetlag credentials
Jetlag credentials
 
Presentation1
Presentation1Presentation1
Presentation1
 
Presentation1
Presentation1Presentation1
Presentation1
 
קורס רשתות חברתיות עבור המי&quot;ל חבר
קורס רשתות חברתיות עבור המי&quot;ל חברקורס רשתות חברתיות עבור המי&quot;ל חבר
קורס רשתות חברתיות עבור המי&quot;ל חבר
 
Brochure Datametrie
Brochure DatametrieBrochure Datametrie
Brochure Datametrie
 
Presentation 3
Presentation 3Presentation 3
Presentation 3
 
Presentation2
Presentation2Presentation2
Presentation2
 

Similar to Alfresco the Clojure Way: Printing Node Names

Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John StevensonJAX London
 
Clojure Interoperability
Clojure InteroperabilityClojure Interoperability
Clojure Interoperabilityrik0
 
APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library
APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures LibraryAPOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library
APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Libraryjexp
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with ClojureJohn Stevenson
 
Exploring Code with Pry!
Exploring Code with Pry!Exploring Code with Pry!
Exploring Code with Pry!Clayton Parker
 
Shell scripting - By Vu Duy Tu from eXo Platform SEA
Shell scripting - By Vu Duy Tu from eXo Platform SEAShell scripting - By Vu Duy Tu from eXo Platform SEA
Shell scripting - By Vu Duy Tu from eXo Platform SEAThuy_Dang
 
(De)serial Killers - BSides Las Vegas & AppSec IL 2018
(De)serial Killers - BSides Las Vegas & AppSec IL 2018(De)serial Killers - BSides Las Vegas & AppSec IL 2018
(De)serial Killers - BSides Las Vegas & AppSec IL 2018Checkmarx
 
(De)serial Killers - BSides Las Vegas & AppSec IL 2018
(De)serial Killers - BSides Las Vegas & AppSec IL 2018(De)serial Killers - BSides Las Vegas & AppSec IL 2018
(De)serial Killers - BSides Las Vegas & AppSec IL 2018Dor Tumarkin
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversBrian Gesiak
 
Ruby is an Acceptable Lisp
Ruby is an Acceptable LispRuby is an Acceptable Lisp
Ruby is an Acceptable LispAstrails
 
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
 
Perl one-liners
Perl one-linersPerl one-liners
Perl one-linersdaoswald
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talkJohn Stevenson
 
Introduction to Functional Programming
Introduction to Functional ProgrammingIntroduction to Functional Programming
Introduction to Functional ProgrammingHoàng Lâm Huỳnh
 

Similar to Alfresco the Clojure Way: Printing Node Names (20)

Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
 
Clojure Interoperability
Clojure InteroperabilityClojure Interoperability
Clojure Interoperability
 
APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library
APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures LibraryAPOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library
APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with Clojure
 
Exploring Code with Pry!
Exploring Code with Pry!Exploring Code with Pry!
Exploring Code with Pry!
 
Shell scripting - By Vu Duy Tu from eXo Platform SEA
Shell scripting - By Vu Duy Tu from eXo Platform SEAShell scripting - By Vu Duy Tu from eXo Platform SEA
Shell scripting - By Vu Duy Tu from eXo Platform SEA
 
(De)serial Killers - BSides Las Vegas & AppSec IL 2018
(De)serial Killers - BSides Las Vegas & AppSec IL 2018(De)serial Killers - BSides Las Vegas & AppSec IL 2018
(De)serial Killers - BSides Las Vegas & AppSec IL 2018
 
(De)serial Killers - BSides Las Vegas & AppSec IL 2018
(De)serial Killers - BSides Las Vegas & AppSec IL 2018(De)serial Killers - BSides Las Vegas & AppSec IL 2018
(De)serial Killers - BSides Las Vegas & AppSec IL 2018
 
9.1 Grand Tour
9.1 Grand Tour9.1 Grand Tour
9.1 Grand Tour
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the Covers
 
Ruby is an Acceptable Lisp
Ruby is an Acceptable LispRuby is an Acceptable Lisp
Ruby is an Acceptable Lisp
 
55j7
55j755j7
55j7
 
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,
 
Perl one-liners
Perl one-linersPerl one-liners
Perl one-liners
 
Shell programming
Shell programmingShell programming
Shell programming
 
Angular Schematics
Angular SchematicsAngular Schematics
Angular Schematics
 
SHELL PROGRAMMING
SHELL PROGRAMMINGSHELL PROGRAMMING
SHELL PROGRAMMING
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talk
 
Introduction to Functional Programming
Introduction to Functional ProgrammingIntroduction to Functional Programming
Introduction to Functional Programming
 
Rakudo
RakudoRakudo
Rakudo
 

Recently uploaded

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 

Recently uploaded (20)

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 

Alfresco the Clojure Way: Printing Node Names

  • 1. Alfresco The Clojure way Carlo Sciolla, Sr R&D Developer at Backbase ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 16. immutability and the art of motorcycle maintenance ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 21. the seq librabry ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 24. fully functional ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 41. concurrency ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 46. the clojure way ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 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 Friday, November 4, 2011
  • 50. John McCarthy 4 September 1927 - 24 October 2011 ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Friday, November 4, 2011
  • 51. Q/A ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Friday, November 4, 2011
  • 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 Friday, November 4, 2011

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n