$30 off During Our Annual Pro Sale. View Details »

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!

    View Slide

  2. #whoami  
    Jérémie Grodziski
    Software Designer and Programmer
    @jgrodziski
    [email protected]
    blog.zenmodeler.com  
    www.redsen.fr/blog  

    View Slide

  3. 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

    View Slide

  4. Essential Functional Programming
    Concepts
    First-Class ,
    Pure and
    Higher-
    Order
    Function
    Immutability
    Recursion
    Lazyness

    View Slide

  5. 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

    View Slide

  6. Higher Order Function
    Takes one or more functions as arguments:
    map, reduce, filter, ...
    Returns a function as a result:
    partial, comp, ...

    View Slide

  7. 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

    View Slide

  8. Function

    View Slide

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

    View Slide

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

    View Slide

  11. 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 »

    View Slide

  12. 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) »

    View Slide

  13. Function bound to symbol
    Anonymous Function
    Function bound to
    symbol « average »
    Shortcut for
    declaring a function
    bound to symbol
    « average »

    View Slide

  14. 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

    View Slide

  15. Recursion
    Mundane recursion
    Use an accumulator
    Recur to the rescue but only in tail position
    and for self recursion

    View Slide

  16. 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

    View Slide

  17. Some scalars
    String
    Boolean
    Numbers
    Keyword
    Symbol

    View Slide

  18. A few Data Structures...
    List
    Vector
    Map
    Set

    View Slide

  19. ...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 »

    View Slide

  20. A lot of built-in Functions
    Etc.
    Excerpt from clojure.org/cheatsheet

    View Slide

  21. 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

    View Slide

  22. 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

    View Slide

  23. 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

    View Slide

  24. REPL Oriented Programming
    Read Eval Print Loop
    A REPL is a mean for interactive development

    View Slide

  25. 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

    View Slide

  26. 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

    View Slide

  27. 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 -

    View Slide

  28. Code is Data
    Vector
    List
    Symbols
    List

    View Slide

  29. Macros
    Code that produce code
    quote `
    unquote ~
    unquote-splicing ~@

    View Slide

  30. Concurrency
    Tranparent: pmap, reducers
    Software Transactional Memory
    Atoms, Ref,
    Actors = Agents
    Core.async (channel and go routine)
    Coordinated Independant
    Synchronous Refs Atoms
    Asynchronous Agents

    View Slide

  31. Java Interoperability
    Java Clojure
    Calling Java from Clojure
    Calling Clojure from Java
    With RT:
    With gen-class:

    View Slide

  32. 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

    View Slide

  33. 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

    View Slide

  34. 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

    View Slide

  35. 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

    View Slide

  36. Clojure Ecosystem: Debugging
    Spyscope
    clojure/tools.trace
    nREPL Ritz, nREPL with a debugger

    View Slide

  37. Clojure Ecosystem: Testing
    clojure.test:
    (deftest),(with-test), (run-test)
    Test stored in function’s meta at :test
    Mocking: (with-redefs), built-in!
    Midje: facts

    View Slide

  38. Clojure Ecosystem: Build
    Leiningen
    Like Maven mais en mieux ! J

    View Slide

  39. 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

    View Slide

  40. Clojure Ecosystem: Database
    •  Drivers to all databases
    •  Datomic

    View Slide

  41. 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

    View Slide

  42. 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.

    View Slide

  43. 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

    View Slide

  44. 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.

    View Slide

  45. 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

    View Slide

  46. Resources: Books
    •  Joy of Clojure
    •  Understanding Computation
    •  SICP

    View Slide

  47. Resources: blogs, personality,
    newsletter
    •  Fogus, rich, chris houser, stuart
    halloway, etc.

    View Slide