Your SlideShare is downloading. ×
Alfresco the clojure way
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Alfresco the clojure way

2,171
views

Published on

An introduction to how to develop Alfresco custom code in the Clojure functional language.

An introduction to how to develop Alfresco custom code in the Clojure functional language.

Published in: Technology

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,171
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
47
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

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

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