What is the clojure equivalent of the Python idiom “if __name__ == ‘__main__'”?

It’s not idiomatic to run Clojure scripts over and over from the command line. The REPL is a better command line. Clojure being a Lisp, it’s common to fire up Clojure and leave the same instance running forever, and interact with it rather than restart it. You can change functions in the running instance one at a time, run them and poke them as needed. Escaping the tedious and slow traditional edit/compile/debug cycle is a great feature of Lisps.

You can easily write functions to do things like run unit tests, and just call those functions from the REPL whenever you want to run them and ignore them otherwise. It’s common in Clojure to use clojure.contrib.test-is, add your test functions to your namespace, then use clojure.contrib.test-is/run-tests to run them all.

Another good reason not to run Clojure from the commandline is that the startup time of the JVM can be prohibitive.

If you really want to run a Clojure script from the command line, there are a bunch of ways you can do it. See the Clojure mailing list for some discussion.

One way is to test for the presence of command line arguments. Given this foo.clj in the current directory:

(ns foo)

(defn hello [x] (println "Hello," x))

(if *command-line-args*
  (hello "command line")
  (hello "REPL"))

You’ll get different behavior depending how you start Clojure.

$ java -cp ~/path/to/clojure.jar:. clojure.main foo.clj --
Hello, command line
$ java -cp ~/path/to/clojure.jar:. clojure.main
Clojure 1.1.0-alpha-SNAPSHOT
user=> (use 'foo)
Hello, REPL
nil
user=>

See src/clj/clojure/main.clj in the Clojure source if you want to see how this is working.

Another way is to compile your code into .class files and invoke them from the Java command line. Given a source file foo.clj:

(ns foo
  (:gen-class))

(defn hello [x] (println "Hello," x))

(defn -main [] (hello "command line"))

Make a directory to store the compiled .class files; this defaults to ./classes. You must make this folder yourself, Clojure won’t create it. Also make sure you set $CLASSPATH to include ./classes and the directory with your source code; I’ll assume foo.clj is in the current directory. So from the command line:

$ mkdir classes
$ java -cp ~/path/to/clojure.jar:./classes:. clojure.main
Clojure 1.1.0-alpha-SNAPSHOT
user=> (compile 'foo)
foo

In the classes directory you will now have a bunch of .class files. To invoke your code from the command line (running the -main function by default):

$ java -cp ~/path/to/clojure.jar:./classes foo
Hello, command line.

There’s a lot of information about compiling Clojure code on clojure.org.

Leave a Comment