Clojure

Other Included Libraries

Other included Libraries

Java Utilities (clojure.java.*)

Access to the initial and current runtime basis, which specifies the libraries and versions currnently loaded on the JVM classpath.

clojure.java.io Contains polymorphic I/O utility functions for Clojure backed by Java classes.

Provides the function javadoc that attempts to display the appropriate Javadocs for a class or instance class.

Support for launching and communicating subprocesses. This namespace supersedes clojure.java.shell and uses the latest Java process APIs.

Provides a sh function that facilitates launching and managing subprocesses. See the function documentation for details on its expected arguments.

Parallel Processing (DEPRECATED)

The parallel library (namespace parallel, in parallel.clj) wraps the ForkJoin library. This lib is now deprecated.

The basic idea is that Clojure collections, and most efficiently vectors, can be turned into parallel arrays for use by this library with the function par, although most of the functions take collections and will call par if needed, so normally you will only need to call par explicitly in order to attach bound/filter/map ops.

Parallel arrays support the attachment of bounds, filters and mapping functions prior to realization/calculation, which happens as the result of any of several operations on the array (pvec/psort/pfilter-nils/pfilter-dupes). Rather than perform composite operations in steps, as would normally be done with sequences, maps and filters are instead attached and thus composed by providing ops to par. Note that there is an order sensitivity to the attachments - bounds precede filters precede mappings. All operations then happen in parallel, using multiple threads and a sophisticated work-stealing system supported by fork-join, either when the array is realized, or to perform aggregate operations like preduce/pmin/pmax etc.

A parallel array can be realized into a Clojure vector using pvec

(load-file "src/parallel.clj")
(refer 'parallel)

(def f (vec (take 20 (repeatedly #(rand-int 20)))))

f
-> [11 7 10 9 4 1 4 18 15 13 10 7 0 9 16 6 19 11 14 7]

;return value/index pairs of all entries < their index, in parallel

(pvec (par f :filter-index < :map-index vector))
-> [[1 5] [4 6] [7 11] [0 12] [9 13] [6 15] [11 17] [14 18] [7 19]]

Reflection Utilities (clojure.reflect)

Provides functions and protocols useful for gathering and building host type reflection information as Clojure data.

REPL Utilities (clojure.repl)

Utilities meant to be used interactively at the REPL.

Sets and Relational Algebra (clojure.set)

Functions useful for manipulating, building, and querying mathematical sets using relational algebra.

String Handling (clojure.string)

Functions for manipulating strings.

Unit Testing (clojure.test)

A Clojure unit testing framework.

Walking Data Structures (clojure.walk)

Utilities for traversing and manipulating nested data structures.

XML (clojure.xml)

Utilities for reading and writing XML data.

Zippers - Functional Tree Editing (clojure.zip)

Clojure includes purely functional, generic tree walking and editing, using a technique called a zipper (in namespace zip) . For background, see the paper by Huet. A zipper is a data structure representing a location in a hierarchical data structure, and the path it took to get there. It provides down/up/left/right navigation, and localized functional 'editing', insertion and removal of nodes. With zippers you can write code that looks like an imperative, destructive walk through a tree, call root when you are done and get a new tree reflecting all the changes, when in fact nothing at all is mutated - it’s all thread safe and shareable. The next function does a depth-first walk, making for easy to understand loops:

(def data '[[a * b] + [c * d]])
(def dz (zip/vector-zip data))

;find the second *
(-> dz zip/down zip/right zip/right zip/down zip/right zip/node)
-> *

;'remove' the first 2 terms
(-> dz zip/next zip/remove zip/next zip/remove zip/root)
-> <<c * d#,c * d>>


;'replace' * with /
(loop [loc dz]
  (if (zip/end? loc)
    (zip/root loc)
    (recur
     (zip/next
      (if (= (zip/node loc) '*)
        (zip/replace loc '/)
        loc)))))

-> [[a / b] + [c / d]]


;'remove' *
(loop [loc dz]
  (if (zip/end? loc)
    (zip/root loc)
    (recur
     (zip/next
      (if (= (zip/node loc) '*)
        (zip/remove loc)
        loc)))))

-> [[a b] + [c d]]


;original is intact
(zip/root dz)
-> [[a * b] + [c * d]]

Zipper constructors are provided for nested seqs, nested vectors, and the xml elements generated by xml/parse. All it takes is a 4-5 line function to support other data structures.