Clojure Marcel Klinzing December 13, 2012 M. Klinzing Clojure 1/18
Overview/History Functional programming language Lisp dialect Compiles to Java Bytecode Implemented in Java Created by Rich Hickey Version 1.0.0 released in 2009 Rich Hickey Current Version: 1.4.0 M. Klinzing Clojure 2/18
Features Program as data First-class functions Dynamically typed Java interoperability Immutable, persistent data Mutable references to data Support for concurrent programming and more... M. Klinzing Clojure 3/18
Forms Part of Clojure called Reader reads chunks of the program called forms Reader translates forms into Clojure data structures Clojure compiles data structures and executes them Forms (excerpt): Form Example Boolean true, false List (+ 1 2), (map + [1 2] [3 4]) Number 1, 3.142, 22/7 String hello world Symbol foo, foo-?, java.lang.thread Vector [1 2 3] M. Klinzing Clojure 4/18
Variables and Functions Defining a (global) variable: (def identifier value) Defining a function: (defn identifier (parameter-vec body) + ) Calling a function: (identifier param1 param2...) 1 (defn f 2 ([] (println "hello, world!")) 3 ([x] (println x))) 4 5 ; brackets can be omitted if 6 ; there is only one parameter vec and body 7 (defn g [] (println "bar")) 8 9 (f) ; Output: hello, world! 10 (f "foo") ; Output: foo 11 (g) ; Output: bar M. Klinzing Clojure 5/18
Destructuring Destructuring used to bind single values in a collection to variables 1 (defn f [ [x y] ] 2 (+ x y)) 3 4 (println (f [1 1])) ; Output: 2 5 (println (f [4 5 6 7])) ; Output: 9 M. Klinzing Clojure 6/18
Java Interoperability Package java.lang imported automatically Create new Object: (new classname & args) Call of variables/methods: (. class-or-instance member-symbol & args) Note that every Clojure function is an Object which implements java.lang.runnable and java.lang.callable 1 (defn delay-print [] 2 (. Thread sleep 100) 3 (println "new Thread")) 4 5 (. (new Thread delay-print) start) 6 (print "start ") 7 ; Output: start new Thread M. Klinzing Clojure 7/18
Reference Types Reference types = mutable references to immutable data Reference types and their purpose: Refs: Synchronous, coordinated updates of data Agents: Asynchronous update of a single value Atoms: Synchronous update of a single value Vars: Synchronous update of a thread-local value M. Klinzing Clojure 8/18
Software Transactional Memory Software Transactional Memory (STM) is a model/concept to view memory as a database STM used for coordinated updates (refs) Updates of values are done in transactions Properties of STM transactions: Atomic updates Consistent updates Isolated updates M. Klinzing Clojure 9/18
STM - Multiversion Control STM uses Multiversion Control (MVCC): Start of a Transaction: Unique ID (called point) is generated Transaction works against private copies of references (associated with the point) Changes to refs will be visible only after the transaction commits/ends If a transaction notices that a ref has been already set/altered by another transaction, the transaction will restart To start a transaction: (dosync & exprs) M. Klinzing Clojure 10/18
Refs Creating a ref: (ref initial-value) Dereferencing a ref: (deref ref-inst) or shorter: @ref-inst To change the reference: (ref-set new-value) Note: ref-set can only be called in a transaction; otherwise a IllegalStateException is thrown M. Klinzing Clojure 11/18
Refs Example 1 (def x (ref 0)) 2 3 (defn increase [] 4 (. Thread sleep 100) 5 (dosync (ref-set x (+ @x 1)))) 6 7 (defn decrease [] 8 (. Thread sleep 100) 9 (dosync (ref-set x (- @x 1)))) 10 11 (def inc-thread (new Thread increase)) 12 (def dec-thread (new Thread decrease)) 13 14 (. inc-thread start) (. dec-thread start) 15 (. inc-thread join) (. dec-thread join) 16 (println @x) ; Output: 0 M. Klinzing Clojure 12/18
Agents Creating an agent: (agent initial-value) Dereferencing for agents as for refs: @agent-inst Changing of agents per update function: (send agent-inst update-fn & args) (update-fn @agent-inst arg1 arg2...) is run later on a thread in a thread pool and the return value is assigned to the agent M. Klinzing Clojure 13/18
Agents Example 1 (def ag (agent 0)) 2 3 (defn increase [x] 4 (+ x 1)) 5 6 (println @(send ag increase)) ; Output: 0 7 (. Thread sleep 100) 8 (println @ag) ; Output: 1 M. Klinzing Clojure 14/18
Benchmark Benchmark taken from the Computer Language Benchmarks Game ( http://shootout.alioth.debian.org ) thread-ring program: Create 503 linked pre-emptive threads Thread 503 should be linked to thread 1, forming an unbroken ring Pass a token to thread 1 Pass the token from thread to thread N times Print the name of the last thread (1 to 503) to take the token M. Klinzing Clojure 15/18
Benchmarks Results (excerpt) N = 50,000,000 Quad-core 2.4Ghz Intel R Q6600 R ; 4GB RAM; 250GB SATA II disk drive x64 Ubuntu TM M. Klinzing Clojure 16/18
Pros: Functional programming (first-class functions, small code,... ) Java interoperability Support for concurrent programming Cons: Speed (since it runs on the JVM) M. Klinzing Clojure 17/18
Other Clojure Implementations ClojureScript Compiles Clojure code to JavaScript implemented in Clojure ClojureCLR Native implementation of Clojure on the Common Language Runtime (CLR; virtual machine of Microsoft s.net framework) Implemented in C# (and Clojure itself) M. Klinzing Clojure 18/18
References Official site: http://clojure.org Book: Stuart Halloway and Aaron Bedra. Programming Clojure. 2nd ed. The Pragmatic Programmers, 2012. Tutorial: R. Mark Volkmann. Clojure - Functional Programming for the JVM http://java.ociweb.com/mark/clojure/article.html Benchmark: http://shootout.alioth.debian.org/ Pictures: Slide 2: http://en.wikipedia.org/wiki/file:rich_hickey.jpg M. Klinzing Clojure
Thank you for your attention. M. Klinzing Clojure
Backup Slides Multimethods Declaring a multimethod: (defmulti identifier choosing-fn) Considering a function call (identifier arg1 arg2...); (choosing-fn arg1 arg2...) is called and the return value determines the implementation to be called Defining a multimethod: (defmethod identifier choosing-val (parameter-vec body) + ) M. Klinzing Clojure
Backup Slides Metadata Metadata = Data about data that doesn t change its logical values Write ^metadata-map before symbols to attach metadata Example: 1 (def x 1) 2 (defn ^{:doc "Returns its first argument"} f [x y] x) 3 4 (println (meta # x)) 5 ; Output: {:ns #<Namespace user>, :name x, :line 1, 6 ; : file D:\Clojure\metadata. clj } 7 (println (meta # f)) 8 ;Output: {: arglists ([x y ]), :ns #<Namespace user>, :name f, 9 ; :doc Returns its first argument, : line 3, : file...} 10 (println (doc f)) 11 ; Output: 12 ; user/f 13 ; ([x y]) 14 ; Returns its first argument M. Klinzing Clojure