SlideShare a Scribd company logo
1 of 46
Download to read offline
Alfresco
                    The Clojure way                                                  Carlo Sciolla, Sr R&D Developer at Backbase




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

Thursday, November 10, 2011
I would like, if I may, to take you on a strange journey.




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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 2011
immutability
                                                   and the art of motorcycle maintenance




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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 2011
concurrency

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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 2011
the seq library

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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 2011
fully functional

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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 2011
the clojure way

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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 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

Thursday, November 10, 2011
John
       McCarthy
       4 September 1927 - 24 October 2011




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

Thursday, November 10, 2011
Q/A

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

Thursday, November 10, 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

Thursday, November 10, 2011

More Related Content

What's hot

Create your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 VeronaCreate your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 VeronaPatrick Allaert
 
Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Nilesh Jayanandana
 
ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overviewhesher
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6Solution4Future
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016Manoj Kumar
 
JRuby @ Boulder Ruby
JRuby @ Boulder RubyJRuby @ Boulder Ruby
JRuby @ Boulder RubyNick Sieger
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScriptQiangning Hong
 
Interceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalInterceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalKent Ohashi
 
Objective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central DispatchObjective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central DispatchMatteo Battaglio
 
API management with Taffy and API Blueprint
API management with Taffy and API BlueprintAPI management with Taffy and API Blueprint
API management with Taffy and API BlueprintKai Koenig
 
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
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation JavascriptRamesh Nair
 
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume LaforgeGroovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume LaforgeGuillaume Laforge
 

What's hot (19)

NIO and NIO2
NIO and NIO2NIO and NIO2
NIO and NIO2
 
Create your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 VeronaCreate your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 Verona
 
Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6
 
ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overview
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
ES6: Features + Rails
ES6: Features + RailsES6: Features + Rails
ES6: Features + Rails
 
JRuby @ Boulder Ruby
JRuby @ Boulder RubyJRuby @ Boulder Ruby
JRuby @ Boulder Ruby
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 
Interceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalInterceptors: Into the Core of Pedestal
Interceptors: Into the Core of Pedestal
 
Objective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central DispatchObjective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central Dispatch
 
Shell script-sec
Shell script-secShell script-sec
Shell script-sec
 
API management with Taffy and API Blueprint
API management with Taffy and API BlueprintAPI management with Taffy and API Blueprint
API management with Taffy and API Blueprint
 
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
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation Javascript
 
Project Coin
Project CoinProject Coin
Project Coin
 
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume LaforgeGroovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
 
JavaScript ES6
JavaScript ES6JavaScript ES6
JavaScript ES6
 

Viewers also liked

萊茵河
萊茵河萊茵河
萊茵河tinaho
 
How to land a Great Job In Videogames
How to land a Great Job In VideogamesHow to land a Great Job In Videogames
How to land a Great Job In VideogamesChris Ansell
 
GMO'less Software Development Practices
GMO'less Software Development PracticesGMO'less Software Development Practices
GMO'less Software Development PracticesLemi Orhan Ergin
 
как превратить идею в капитал
как превратить идею в капиталкак превратить идею в капитал
как превратить идею в капиталPavel Gorbunov
 
Building Social Networks in the University -- Ignite Salt Lake 2
Building Social Networks in the University -- Ignite Salt Lake 2Building Social Networks in the University -- Ignite Salt Lake 2
Building Social Networks in the University -- Ignite Salt Lake 2Kyle Mathews
 
Torben Budde CV 201502 (English)
Torben Budde CV 201502 (English)Torben Budde CV 201502 (English)
Torben Budde CV 201502 (English)Torben Budde
 
Which Superhero Flies Highest on Social Media?
Which Superhero Flies Highest on Social Media?Which Superhero Flies Highest on Social Media?
Which Superhero Flies Highest on Social Media?Mashable
 
Электрочайник с термодатчиком на эффекте памяти формы.
Электрочайник с термодатчиком на эффекте памяти формы.Электрочайник с термодатчиком на эффекте памяти формы.
Электрочайник с термодатчиком на эффекте памяти формы.kulibin
 
0423_導入ゼミ_増田優斗「東京武道館」
0423_導入ゼミ_増田優斗「東京武道館」0423_導入ゼミ_増田優斗「東京武道館」
0423_導入ゼミ_増田優斗「東京武道館」優斗 増田
 
QoS marking on cisco IOS Router
QoS marking on cisco IOS RouterQoS marking on cisco IOS Router
QoS marking on cisco IOS RouterNetProtocol Xpert
 

Viewers also liked (20)

萊茵河
萊茵河萊茵河
萊茵河
 
Wykładzina vol. 15 ClickMeeting - make your Webinar click!
Wykładzina vol. 15 ClickMeeting - make your Webinar click!Wykładzina vol. 15 ClickMeeting - make your Webinar click!
Wykładzina vol. 15 ClickMeeting - make your Webinar click!
 
How to land a Great Job In Videogames
How to land a Great Job In VideogamesHow to land a Great Job In Videogames
How to land a Great Job In Videogames
 
GMO'less Software Development Practices
GMO'less Software Development PracticesGMO'less Software Development Practices
GMO'less Software Development Practices
 
2nd Annual Mobile Apps 2013
2nd   Annual Mobile Apps 20132nd   Annual Mobile Apps 2013
2nd Annual Mobile Apps 2013
 
Success portfolio
Success portfolioSuccess portfolio
Success portfolio
 
[Video] The Run
[Video] The Run[Video] The Run
[Video] The Run
 
Steve jobs
Steve jobsSteve jobs
Steve jobs
 
La muerte de la virgen
La muerte de la virgenLa muerte de la virgen
La muerte de la virgen
 
Practica no3
Practica no3Practica no3
Practica no3
 
как превратить идею в капитал
как превратить идею в капиталкак превратить идею в капитал
как превратить идею в капитал
 
Building Social Networks in the University -- Ignite Salt Lake 2
Building Social Networks in the University -- Ignite Salt Lake 2Building Social Networks in the University -- Ignite Salt Lake 2
Building Social Networks in the University -- Ignite Salt Lake 2
 
Torben Budde CV 201502 (English)
Torben Budde CV 201502 (English)Torben Budde CV 201502 (English)
Torben Budde CV 201502 (English)
 
Which Superhero Flies Highest on Social Media?
Which Superhero Flies Highest on Social Media?Which Superhero Flies Highest on Social Media?
Which Superhero Flies Highest on Social Media?
 
Электрочайник с термодатчиком на эффекте памяти формы.
Электрочайник с термодатчиком на эффекте памяти формы.Электрочайник с термодатчиком на эффекте памяти формы.
Электрочайник с термодатчиком на эффекте памяти формы.
 
0423_導入ゼミ_増田優斗「東京武道館」
0423_導入ゼミ_増田優斗「東京武道館」0423_導入ゼミ_増田優斗「東京武道館」
0423_導入ゼミ_増田優斗「東京武道館」
 
Io t asia summit 2015
Io t asia summit 2015Io t asia summit 2015
Io t asia summit 2015
 
QoS marking on cisco IOS Router
QoS marking on cisco IOS RouterQoS marking on cisco IOS Router
QoS marking on cisco IOS Router
 
Contaminacion
ContaminacionContaminacion
Contaminacion
 
Break the rules - The FOG
Break the rules - The FOGBreak the rules - The FOG
Break the rules - The FOG
 

Similar to Alfresco the clojure way -- Slides from the Alfresco DevCon2011

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
 
Capistrano - automate all the things
Capistrano - automate all the thingsCapistrano - automate all the things
Capistrano - automate all the thingsJohn Cleary
 
Clojure Interoperability
Clojure InteroperabilityClojure Interoperability
Clojure Interoperabilityrik0
 
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
 
Exploring Code with Pry!
Exploring Code with Pry!Exploring Code with Pry!
Exploring Code with Pry!Clayton Parker
 
De vuelta al pasado con SQL y stored procedures
De vuelta al pasado con SQL y stored proceduresDe vuelta al pasado con SQL y stored procedures
De vuelta al pasado con SQL y stored proceduresNorman Clarke
 
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
 
(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
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)Pavlo Baron
 
Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Matt Aimonetti
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talkJohn Stevenson
 
Postgresql function_basics.pdf
Postgresql function_basics.pdfPostgresql function_basics.pdf
Postgresql function_basics.pdfsvhtayrv
 
Perl one-liners
Perl one-linersPerl one-liners
Perl one-linersdaoswald
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Introthnetos
 

Similar to Alfresco the clojure way -- Slides from the Alfresco DevCon2011 (20)

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
 
Capistrano - automate all the things
Capistrano - automate all the thingsCapistrano - automate all the things
Capistrano - automate all the things
 
Clojure Interoperability
Clojure InteroperabilityClojure Interoperability
Clojure Interoperability
 
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
 
Exploring Code with Pry!
Exploring Code with Pry!Exploring Code with Pry!
Exploring Code with Pry!
 
9.1 Grand Tour
9.1 Grand Tour9.1 Grand Tour
9.1 Grand Tour
 
De vuelta al pasado con SQL y stored procedures
De vuelta al pasado con SQL y stored proceduresDe vuelta al pasado con SQL y stored procedures
De vuelta al pasado con SQL y stored procedures
 
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
 
Angular Schematics
Angular SchematicsAngular Schematics
Angular Schematics
 
(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
 
55j7
55j755j7
55j7
 
9.1 Mystery Tour
9.1 Mystery Tour9.1 Mystery Tour
9.1 Mystery Tour
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010
 
Clojure made simple - Lightning talk
Clojure made simple - Lightning talkClojure made simple - Lightning talk
Clojure made simple - Lightning talk
 
Postgresql function_basics.pdf
Postgresql function_basics.pdfPostgresql function_basics.pdf
Postgresql function_basics.pdf
 
Perl one-liners
Perl one-linersPerl one-liners
Perl one-liners
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 

Recently uploaded

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
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
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
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
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
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
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
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
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
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 

Recently uploaded (20)

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
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
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
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
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
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
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.
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 

Alfresco the clojure way -- Slides from the Alfresco DevCon2011

  • 1. Alfresco The Clojure way Carlo Sciolla, Sr R&D Developer at Backbase ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 2. I would like, if I may, to take you on a strange journey. ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 3. 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 Thursday, November 10, 2011
  • 4. (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 Thursday, November 10, 2011
  • 5. (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 Thursday, November 10, 2011
  • 6. (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 Thursday, November 10, 2011
  • 7. (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 Thursday, November 10, 2011
  • 8. (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 Thursday, November 10, 2011
  • 9. (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 Thursday, November 10, 2011
  • 10. 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 Thursday, November 10, 2011
  • 11. the sexp and the city or: How I learned to stop worrying and love the parens ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 12. 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 Thursday, November 10, 2011
  • 13. 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 Thursday, November 10, 2011
  • 14. 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 Thursday, November 10, 2011
  • 15. 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 Thursday, November 10, 2011
  • 16. immutability and the art of motorcycle maintenance ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 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 Thursday, November 10, 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 Thursday, November 10, 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 Thursday, November 10, 2011
  • 20. concurrency ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 21. 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 Thursday, November 10, 2011
  • 22. 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 Thursday, November 10, 2011
  • 23. (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 Thursday, November 10, 2011
  • 24. 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 Thursday, November 10, 2011
  • 25. the seq library ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 26. 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 Thursday, November 10, 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 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 Thursday, November 10, 2011
  • 28. fully functional ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 29. (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 Thursday, November 10, 2011
  • 30. 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 Thursday, November 10, 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. 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 Thursday, November 10, 2011
  • 32. 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 Thursday, November 10, 2011
  • 33. (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 Thursday, November 10, 2011
  • 34. 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 Thursday, November 10, 2011
  • 35. (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 Thursday, November 10, 2011
  • 36. (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 Thursday, November 10, 2011
  • 37. 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 Thursday, November 10, 2011
  • 38. 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 Thursday, November 10, 2011
  • 39. + $ 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 Thursday, November 10, 2011
  • 40. the clojure way ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 41. (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 Thursday, November 10, 2011
  • 42. (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 Thursday, November 10, 2011
  • 43. (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 Thursday, November 10, 2011
  • 44. John McCarthy 4 September 1927 - 24 October 2011 ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 45. Q/A ALFRESCO THE CLOJURE WAY | November 8, 2011 | @skuro Thursday, November 10, 2011
  • 46. 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 Thursday, November 10, 2011