I’m dabbling in clojure and am having a little trouble trying to determine the clojure (and / or Lisp) equivalent of this common python idiom.
The idiom is that at the bottom of a python module there is often a bit of test code, and then a statement which runs the code, for example:
# mymodule.py
class MyClass(object):
"""Main logic / code for the library lives here"""
pass
def _runTests():
# Code which tests various aspects of MyClass...
mc = MyClass() # etc...
assert 2 + 2 == 4
if __name__ == '__main__': _runTests()
This is useful for simple, ad-hoc testing. One would normally use this module by writing from mymodule import MyClass, in which case _runTests() is never called, but with the snippet at the end, one can also run it by typing python mymodule.py directly from the command line.
Is there an equivalent idiom in Clojure (and/or common lisp)? I’m not after a full-blown unit testing library (well, I am, but not in this question), I’d just like to include some code in a module which will only be run under some circumstances, so I can have a quick way to run code I’ve been working on but still allow my file to be imported like a normal module / namespace.
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 useclojure.contrib.test-is/run-teststo 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.cljin the current directory:You’ll get different behavior depending how you start Clojure.
See
src/clj/clojure/main.cljin the Clojure source if you want to see how this is working.Another way is to compile your code into
.classfiles and invoke them from the Java command line. Given a source filefoo.clj:Make a directory to store the compiled
.classfiles; this defaults to./classes. You must make this folder yourself, Clojure won’t create it. Also make sure you set$CLASSPATHto include./classesand the directory with your source code; I’ll assumefoo.cljis in the current directory. So from the command line:In the
classesdirectory you will now have a bunch of.classfiles. To invoke your code from the command line (running the-mainfunction by default):There’s a lot of information about compiling Clojure code on clojure.org.