Being able to write, build and run a Clojure application, like I explained in a previous article, is not enough. You also want to hack on it, to iterative code on it, after all, you are using a Lisp.
What I mean by iterative coding is something not very few know or do, but it’s extremely common in Lisp. You have you REPL running all the time (that is, generally, the interpreter). You load the code into the REPL, run it, modify some part of the code and re-load it. You may not reload the whole file but only a function on it, and you may have background process running on the REPL, like a web server. It is very powerful.
After I made the application just like in How to create a Clojure application I’ve found out that I couldn’t just load the file into Slime because the Clojure REPL process didn’t have the right class-path.
I’ve found two solutions for this problem. Let’s start with the one I’m actually using. If I run this:
mvn dependency:copy-dependencies
on a Maven project I end up with all the dependency jars in the directory target/dependency. Having all files in one location makes it easier. I just write a project.el in the directory of my project containing something like:
(add-to-list 'swank-clojure-extra-classpaths (expand-file-name "target/dependency/*" (file-name-directory load-file-name)))
and I load that file (M-xload-file<return>project.el<return>) before I start to work on the project. It is like opening the project. After that, firing Slime just works. It seems it’s not possible to change the class-path of a running Java process, which means that when dependencies change, I’ll have to restart your REPL anyway. I suppose the JVM designers were not thinking on interactive programming environments when they designed it. Hopefully this would only be a problem at the start of a project.
The other solution is to run:
mvn dependency:build-classpath
which the way I configure it, it outputs the class-path to target/classpath, looking something like:
/home/pupeno/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar:/home/pupeno/.m2/repository/jvm/clojure/clojure-lang/1.0-SNAPSHOT/clojure-lang-1.0-SNAPSHOT.jar:/home/pupeno/.m2/repository/trail-taglib/trail-taglib/0.2/trail-taglib-0.2.jar
which then I can use to set the class-path of the Slime process. I was about to write a Emacs Lisp function to load that file and set the class-path, but my knowledge of Emacs Lisp is very limited and I want to code in Clojure, not Emacs Lisp, so I didn’t make this way work, although I believe it’s the cleaner.
I’ve also tried working with Enclojure in NetBeans. It should just work, but I’ve got an error installing the latest Enclojure in the latest NetBeans and I just reverted to good old Emacs.
If you haven’t noticed, this is another article mainly for myself.
Leave a Reply