Upgrade to Pro — share decks privately, control downloads, hide ads and more …

An introduction to Clojure

An introduction to Clojure

Jérémie Grodziski

October 17, 2013
Tweet

More Decks by Jérémie Grodziski

Other Decks in Programming

Transcript

  1. Clojure! An Introduction! with bits of Domain-Driven Design and Functional

    Databases...! ! Java User Group Lausanne – Oct 2013!
  2. Clojure is... Functional Dynamic a dialect of LISP Homoiconic (a.k.a.

    Code is Data, Data is Code) Immutable by default using Runtime Polymorphism Concurrent Hosted on the JVM
  3. First-class Function Composable: – can be created on demand, – stored in

    a data structure, – passed as an argument to a function, – returned as the value of a function
  4. Higher Order Function Takes one or more functions as arguments:

    map, reduce, filter, ... Returns a function as a result: partial, comp, ...
  5. Pure Function Always return the same results given the same

    arguments Doesn’t cause any observable side-effects Allows referential transparency as time does not affect the result of a function invocation (function is transparent to time) Allows memoization, algebraic manipulation and increase testability
  6. Function Arguments Body Return the last expression Function invocation Anonymous

    function declaration = Lambda Result bound to symbol Invocation’s Arguments
  7. Function Arguments Body Return the last expression Function invocation Named

    function declaration Result bound to symbol Invocation’s Arguments
  8. Binding « Binding » = assigning a value to a

    symbol in a scope In Clojure, everything is an expression and return a value NO VARIABLE and NO STATEMENT ! But provide Software Transactional Memory for shared « variable »
  9. The « let » special form Can be thought of

    as saying: « Let symbol sum have the value of expression (reduce + numbers) and symbol nb-of-items have the value of expression (count numbers) in body (/ sum nb-of-items) »
  10. Function bound to symbol Anonymous Function Function bound to symbol

    « average » Shortcut for declaring a function bound to symbol « average »
  11. Immutability All of the possible properties of immutable objects are

    defined at the time of their construction and can’t be changed thereafter How to get something done if things can’t change ? Use recursion instead of mutation with persistent data structure that allows structural sharing
  12. Recursion Mundane recursion Use an accumulator Recur to the rescue

    but only in tail position and for self recursion
  13. Lazyness Realize the result of an expression when it is

    really needed != eager (eager = statement or arguments to function are immediately evaluated) Java && (logical and) has lazy evaluation Clojure’s sequence are lazy, allows infinite sequence
  14. ...and a lot of Functions Alan J. Perlis, developed Algol

    language, 1st recipient of the Turing Award For other « Perlism »:http://www.cs.yale.edu/quotes.html « It is better to have 100 functions operate on 1 data structure than 10 functions on 10 data structures »
  15. Persistent Data Structure When a persistent data structure is "modified,"

    the data is not mutated. Rather, a new immutable version of the data structure is returned Structural sharing is the technique used to make Clojure's persistent data structures efficient Structural sharing relies on the data's immutability to make sharing possible between the old and new instances of the data
  16. Clojure Philosophy or « In the brain of Rich Hickey

    » Simplicity, freedom to focus, empowerment, consistency, and clarity Value Driven Programming or Facts-Oriented Programming instead of Place-Oriented Programming Libraries not Frameworks
  17. Dynamic A Clojure program is not just something you compile

    and run, but something with which you can interact ⇒ REPL Oriented Programming Anything you enter into the REPL or load using load-file is automatically compiled to JVM bytecode on the fly
  18. Clojure is a Lisp dialect Lambda calculus yields an extremely

    small core Almost no syntax Core advantage still code-as-data and syntactic abstraction What about the standard Lisps (Common Lisp and Scheme)? –  Slow/no innovation post standardization –  Core data structures mutable, not extensible –  No concurrency in specs –  Good implementations already exist for JVM (ABCL, Kawa, SISC et al) –  Standard Lisps are their own platforms Clojure is a Lisp not constrained by backwards compatibility –  Extends the code-as-data paradigm to maps and vectors –  Defaults to immutability –  Core data structures are extensible abstractions –  Embraces a platform (JVM) excerpt from clojure.org/rationale
  19. A dialect of LISP: everything is an expression In clojure,

    everything is an expression that return a value, there are no statements, hence the term « value-based programming ». Clojure: returns true or false (so can be evaluated) Java: returns nothing but can change state
  20. A dialect of LISP: Homoiconicity All Code in Clojure are

    list in the form It enables very powerful meta-programming (quote exp) and (eval exp) « Code is Data, Data is Code » from homo - the same - and icon - representation -
  21. Concurrency Tranparent: pmap, reducers Software Transactional Memory Atoms, Ref, Actors

    = Agents Core.async (channel and go routine) Coordinated Independant Synchronous Refs Atoms Asynchronous Agents
  22. Temporal aspect of State management and Identity Identity Single Married

    Adult Minor Time Adult state Marital state Divorced •  Business Id : 12345678 •  John •  Doe •  5 November 1976 in Paris •  … Entity State Entity Object at a given moment in time Identity State
  23. State, Identity and Function State Identity State 1 State 2

    State 3 Function Function Event triggers Event triggers •  value 1a •  value 1b •  value 1c •  value 1a •  value 1b •  value 1c •  value 2a •  value 2b •  value 1a •  value 1b •  value 1c •  value 2a •  value 2b •  value 3a Publish Internal Event Publish Internal Event ... Time
  24. Example with Order entity Identity : Order N° 123456 Submitted

    Paid Shipped pay ship Payment details from Payment Gateway received Carrier data q  Customer Data q  Product Lines (product + qty) q  Shipping Data States submit q  Customer Data q  Product Lines (product + qty) q  Shipping Data q  Payment Data q  Customer Data q  Product Lines (product + qty) q  Shipping Data q  Payment Data q  Carrier Data Front website form submitted Order submitted event Order paid event Order shipped event Time
  25. OOP done right with Clojure Identity State as values Function

    Method = function applied to an identity’s state, [eventually producing a new state] Entity = Identity + State Protocol = Interface = set of methods
  26. Clojure Ecosystem: Web Request and Response plumbing (HTTP) – Ring Routing

    Request to a Handler (function) – Compojure Templating the response from the handler – Hiccup and Enlive
  27. Datomic Datomic is a database of flexible, time- based facts,

    supporting queries and joins, with elastic scalability, and ACID transactions We’ll cover Datomic Data Model, Architecture and Programming Model
  28. Datomic Data Model Immutable Data –  Data consisting of immutable

    values. How? facts don’t change when you incorporate time in the data. Time in data allows the past to be retained (or not), and supports point-in-time queries. 'latest' view in traditional database vs retaining all changes. Datomic is a database of facts, not places. Atomic Data - the Datom –  Facts are recorded as independent atoms of information. Datomic calls such atomic facts 'datoms'. A datom consists of an entity, attribute, value and transaction (time). Minimal Schema –  All databases have a schema, whether they are written down or not. The schema required to encode datoms consisting primarily of the attribute definitions, which specify name, type, cardinality etc. The Database –  A Datomic database is just a set of datoms, indexed in various ways. These indexes contain all of the data, not pointers to data (i.e. they are covering indexes). The storage service and caches are just a distribution network for the data segments of these indexes, all of which are immutable, and thus effectively and coherently cached.
  29. Datomic breaks traditional DB services apart Peers: The peer component

    is a library that gets embedded in the applications –  Submits transactions to, and accepts changes from, the transactor –  Includes all communication components for talking to transactors and storage services –  Provides data access, caching, and query capability to the application, reading from the storage service as needed Transactors –  Accept transactions –  Process them serially –  Commit the results to the storage service –  all writes are synchronously made to redundant storage –  Transmit changes to the peers –  Index in the background, place indexes in storage service Storage services –  Provide an interface to highly reliable, redundant storage –  Available from third-parties: Amazon DynamoDB, RDBMS, Infinispan
  30. Benefits of Datomic Architecture Separating reads and writes –  When

    reads are separated from writes, writes are never held up by queries. In the Datomic architecture, the transactor is dedicated to transactions, and need not service reads at all! Integrated data distribution –  Each peer and transactor manages its own local cache of data segments, in memory. This cache self-tunes to the working set of that application. Every peer gets its own brain (query engine and cache) –  Traditional client-server databases leads to impedance mismatch. The problem, though, isn't that databases are insufficiently object-oriented, rather, that applications are insufficiently declarative. Moving a proper, index-supported, declarative query engine into applications will enable them to work with data at a higher level than ever before, and at application-memory speeds. Elasticity –  Application servers are frequently scaled up and down as demand fluctuates, but traditional databases, even with read-replication configured, have difficulty scaling query capability similarly. Putting query engines in peers makes query capability as elastic as the applications themselves. In addition, putting query engines into the applications themselves means they never wait on each other's queries. Ready for the cloud –  All components are designed to run on commodity servers, with expectations that they, and their attached storage, are ephemeral. The speed of memory –  While the (disk-backed) storage service constitutes the data of record, the rest of the system operates primarily in memory.
  31. DDD in Clojure •  DDD is about introducing the domain

    language into the source code •  Clojure’s idiom is about (very) short name –  Ex: def instead of define, inc instead of increment, etc. –  That’s not oriented towards understandability but conciseness •  Weak typing means a different way of looking after the domain language –  Symbols instead of type’s name •  The fundamentals of the language are indeed very DDD oriented –  Everything returns a Value –  Identity, State and Functions does not complects in Entity