(ns com.my-company.clojure.examples.my-utils
(:import java.util.Date)
(:use [clojure.string :only (join)])
(:require [clojure.java.io :as jio]))
Clojure provides for code loading and dependency tracking via its "lib" facility. A lib is a named unit of Clojure source code contained in a Java resource within classpath. A lib will typically provide the complete set of definitions that make up one Clojure namespace.
Clojure defines conventions for naming and structuring libs:
A lib name is a symbol that will typically contain two or more parts separated by periods.
A lib’s container is a Java resource whose classpath-relative path is derived from the lib name:
The path is a string
Periods in the lib name are replaced by slashes in the path
Hyphens in the lib name are replaced by underscores in the path
The path may end with ".class", ".clj", or ".cljc" (see Lib load order below)
A lib begins with an "ns" form that
creates the Clojure namespace that shares its name, and
declares its dependencies on Java classes, Clojure’s core facilities, and/or other libs,
Clojure ensures that if the call to "ns" completes without throwing an exception, the declared dependencies have been satisfied and the capabilities they provide are available.
A simple lib:
(ns com.my-company.clojure.examples.my-utils
(:import java.util.Date)
(:use [clojure.string :only (join)])
(:require [clojure.java.io :as jio]))
The ns
form names the lib’s namespace and declares its dependencies. Based on its name, this lib is typically defined in a source file at the classpath-relative path: com/my_company/clojure/examples/my_utils.clj (note the translations from period to slash and hyphen to underscore).
The :import
clause declares this lib’s use of java.util.Date
and makes it available to code in this lib using its unqualified name.
The :use
clause declares a dependency on the clojure.string
lib for its join
function only. join may be used in this lib’s code using its unqualified name.
The :require
clause declares a dependency on the clojure.java.io
lib and enables using its members using the shorter namespace alias jio
.
It’s common for a lib to depend on several other libs whose full names share a common prefix. In calls to require
and use
(and in :require
and :use
clauses within an ns form), the common prefix can be extracted and provided once using a prefix list. For example, these two forms are equivalent:
(require 'clojure.contrib.def 'clojure.contrib.except 'clojure.contrib.sql)
(require '(clojure.contrib def except sql))
Libs may exist in either compiled (.class
) or source (.clj
or .cljc
) form. In some cases, one or even all of these might exist on the classpath. The lib is loaded from one of them based on the following rules:
A .class
file is always preferred over a source file, unless the source file’s timestamp is newer than the .class
file, in which case the source file is preferred.
A .clj
(platform-specific file) is always preferred over a .cljc
(common across platforms).
The second rule allows a library author to ship both a portable common definition of a lib while also shipping platform-specific libs that override the portable version to do something that leverages the host platform.