We're coming around the other side of the few breaking changes I
wanted to get done before release 1.0.
The changes are:
New regex format:
Uniform binding syntax using vectors:
And ahead-of-time (AOT) compilation (SVN 1094+)
There is now an AOT compiler that can compile .clj files to .class
files on disk. This can be used to save startup time, deliver
applications without source, interop with bytecode-based tools etc.
The main structural change related to AOT is that the mapping between
a Clojure namespace and a Java package has changed. Where it was ns
maps to package:
my.fancy.lib ==> my/fancy/lib/lib.clj
it is now ns maps to class:
my.fancy.lib ==> my/fancy/lib.clj, when compiled, my/fancy/lib.class
Just lift your files up a directory to accommodate this change. Note
that this implies that all namespaces should have at least 2 segments,
and following the Java package name guidelines, e.g.
com.mydomain.mylib, is recommended.
Accordingly, the clojure ns has been renamed clojure.core. Any
explicitly qualified references will need to be changed. boot.clj has
been renamed core.clj.
The only other source-level change here was a small one to load - you
no longer should supply the .clj extension, in keeping with load's new
ability to load from .class files.
The latter is the only functional difference AOT brings to existing
code - load will load from a .class file if it is newer than the .clj.
Both files need to be in the classpath, using a directory structure
corresponding the the Java package as per above. Once compiled, .clj
files need not be present at all if .class files are supplied.
The unit of compilation is the lib. To compile a lib, simple say:
The source must be in the classpath, in my/fancy/lib.clj Compilation
output will go under the path designated by *compile-path*, which
defaults to the "classes" directory under cwd. Output will go to
*compile-path*/my/fancy/lib.class, and the subdirectories will be
created if needed. *compile-path* is bound in the repl and can be set!
or bound with binding. The *compile-path* directory must also be in
Compilation occurs under a same-world model, i.e. compiling a file has
the effect of loading it as well. As each file/fn is compiled, it is
loaded using the standard class lookup (thus the *compile-path* in
classpath requirement above). This is so that definitions can see and
utilize the definitions and macros that preceded them. While
compiling, a *compile-files* flag is set. This will cause nested load/
require/uses to compile as well, if needed. If your file has some def
initializers you don't want to run at compile-time, you can
conditionalize them like this:
(def foo (when-not *compile-files* (my-runtime-init)))
in which case foo will be nil at compile time.
A .class file will be produced for every file loaded. This file
defines a class called my.fancy.lib, which will have a static void load
() method (this name is likely to change). Calling this method has the
same effect as loading the original .clj would.
Namespaces defined in multiple files are supported. Simply (load "lib-
helper-file") for any helper files at the bottom of your ns-
defining .clj file. Note that classes will be created for these files
as well, even though they are not namespaces, and are not intended for
In addition to the class file per .clj file, there will be a .class
file for every function. These will be named my/fancy/lib
$myfun__xxxx.class. They too are not intended for standalone use.
There will be many of these, so please use jar files for distribution.
The clojure.contrib and tools folks are working on getting in sync
with these changes. For minimal disruption, please stick with the SVN
rev they support (say, 1088), or lend a hand in testing their patches.
Still to come is a folding of genclass functionality into AOT, making
for a much smoother process.
Those of you who've used Clojure for a while know such breaking
changes are few and far between. AOT compilation is an important, non-
trivial, and often requested feature. Please be patient during the
As always, feedback and bug reports welcome.