Jérémie Grodziski
October 17, 2013
4.9k

# An introduction to Clojure

October 17, 2013

## Transcript

1. Clojure!
An Introduction!
with bits of Domain-Driven Design and
Functional Databases...!
!
Java User Group Lausanne – Oct 2013!

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

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

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

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

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

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

8. Function

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

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

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 »

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

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

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

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

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

17. Some scalars
String
Boolean
Numbers
Keyword
Symbol

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

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 »

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

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

22. Clojure Philosophy or « In the
brain of Rich Hickey »
Simplicity, freedom to focus, empowerment,
consistency, and clarity
Value Driven Programming or Facts-Oriented
Libraries not Frameworks

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
to JVM bytecode on the fly

24. REPL Oriented Programming
A REPL is a mean for interactive development

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

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

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 -

28. Code is Data
Vector
List
Symbols
List

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

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

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

32. Temporal aspect of State
management and Identity
Identity
Single Married
Minor
Time
Marital state Divorced
•  John
•  Doe
•  5 November 1976 in Paris
•  …
Entity
State
Entity Object at a given
moment in time
Identity State

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

34. Example with Order entity
Identity : Order N° 123456
Submitted Paid Shipped
pay ship
Payment details
from Payment
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

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

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

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

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

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

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

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

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.

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

44. Benefits of Datomic Architecture
–  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.
–  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.

45. DDD in Clojure
•  DDD is about introducing the domain language into
the source code
•  Clojure’s idiom is about (very) short name
–  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

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

47. Resources: blogs, personality,