Recently Added Features

Reader Literals

Clojure 1.4 supports reader literals, which are data structures tagged by a symbol to denote how they will be read.
When Clojure starts, it searches for files named data_readers.clj at the root of the classpath. Each such file must contain a Clojure map of symbols, like this:
 foo/baz my.project/baz}
The key in each pair is a tag that will be recognized by the Clojure reader. The value in the pair is the fully-qualified name of a Var which will be invoked by the reader to parse the form following the tag. For example, given the data_readers.clj file above, the Clojure reader would parse this form:
#foo/bar [1 2 3]

by invoking the Var #' on the vector [1 2 3]. The data reader function is invoked on the form AFTER it has been read as a normal Clojure data structure by the reader.

Reader tags without namespace qualifiers are reserved for Clojure. Default reader tags are defined inclojure.core/default-data-readers but may be overridden in data_readers.clj or by rebinding *data-readers*.

Instant Literals
Clojure supports literals for instants in the form #inst "yyyy-mm-ddThh:mm:ss.fff+hh:mm". These literals are parsed asjava.util.Dates by default. They can be parsed as java.util.Calendars or java.util.Timestamps by binding*data-readers* to use clojure.instant/read-instant-calendar or clojure.instant/read-instant-timestamp.
(def instant "#inst \"@2010-11-12T13:14:15.666\"")
; Instants are read as java.util.Date by default
(= java.util.Date (class (read-string instant)))
;=> true
; Instants can be read as java.util.Calendar or java.util.Timestamp
(binding [*data-readers* {'inst read-instant-calendar}]
  (= java.util.Calendar (class (read-string instant))))
;=> true
(binding [*data-readers* {'inst read-instant-timestamp}]
  (= java.util.Timestamp (class (read-string instant))))
;=> true

UUID Literals
Clojure supports literals for UUIDs in the form #uuid "uuid-string". These literals are parsed as java.util.UUIDs.

Enhanced Primitives

Clojure supports optimization of functions, records and types via type hinting. By adding metadata to the arguments of a function a fast-path is created by the compiler which does not perform boxing of primitives. This often will lead to a dramatic boost in performance:

(defn fib [n]
  (if (<= n 1)
    (+ (fib (dec n)) (fib (- n 2)))))
(time (fib 38))
"Elapsed time: 2973 msecs"
;; hint arg and return
(defn fib ^long [^long n]
  (if (<= n 1)
    (+ (fib (dec n)) (fib (- n 2)))))
(time (fib 38))
"Elapsed time: 390 msecs"
;; double arg/return
(defn fib ^double [^double n]
  (if (<= n 1)
    (+ (fib (dec n)) (fib (- n 2)))))
(time (fib 38))
"Elapsed time: 944 msecs"
;; double arg/return, double operands
(defn fib ^double [^double n]
  (if (<= n 1.0)
    (+ (fib (dec n)) (fib (- n 2.0)))))
(time (fib 38))
"Elapsed time: 448 msecs"


Reducers provide a set of high performance functions for working with collections. The actual fold/reduce algorithms are specified via the collection being reduced. This allows each collection to define the most efficient way to reduce its contents.
The implementation details of reducers are available at the Clojure blog
user=> (require '[clojure.core.reducers :as r])
user=> (reduce + (r/filter even? (r/map inc [1 1 1 2])))
;=> 6
;;red is a reducer awaiting a collection
user=> (def red (comp (r/filter even?) (r/map inc)))
user=> (reduce + (red [1 1 1 2]))
;=> 6
user=> (into #{} (r/filter even? (r/map inc [1 1 1 2])))
;=> #{2}

Logo & site design by Tom Hickey.