By Tim Gilbert

2009-06-10 00:07:58 8 Comments

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:

class MyClass(object):
    """Main logic / code for the library lives here"""

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 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.


@nha 2016-02-10 15:19:51

Boot is a build tooling (an alternative to leiningen), that supports scripts. So you could have a boot script beginning with #!/usr/bin/env boot that can have a -main method.

You could also make tasks invoked from the command line that would call up different functions of your code. And you could have a packaging task that can create an uberjar for one of these functions as entry points.

@steglig 2011-05-19 16:17:58

There's also a list of different possibilities at (If you find a new one - please add it. ;-))

@Chris 2009-06-18 04:11:40

If you are talking about having an "entry point" you can certainly do that:

(ns foo)

(defn foo [n]
  (inc n))

(defn main []
  (println "working")
  (println "Foo has ran:" (foo 1)))


what will happen now is that any time this code is (load-file "foo.clj")'d or (use 'foo) or (require 'foo), then (main) will be called, that's usually not done.

Much more common is that a file of code can be loaded at the REPL and then the main function would be called by the user.

@mcandre 2010-11-24 22:17:56

Can this be done in such a way that (main) is only triggered when foo.clj is run directly and not when another script loads it?

@Chris 2010-11-27 04:10:38

I don't think so because in both cases you'd be evaluating (and then compiling) all the expressions. There's always AOT compilation which allows for the definition of an entry-point:

@Brian Carper 2009-06-10 08:18:39

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

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

(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)

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

@dmitry_vk 2009-06-10 06:10:12

Common Lisp and Clojure (as well as other lisps) provide interactive environment with REPL, and you do not need tricks like «if __name__ == '__main__'». There are REPL-like environments for python: the python from command-line, ipython, python mode for Emacs, etc.

You should just create the library, add a testsuite to it (there are many testing frameworks for Common Lisp; I prefer the 5am framework, there is a survey of frameworks available here). And then you load the library, and in the REPL you can do anything with the library: run tests, call functions, experiment, etc.

When you find a failing test, you make a fix to it, recompile the changed code, and continue experimenting, running tests without restarting the whole application. This saves a lot of time, because the running application might have accumulated a lot of state (it might have created gui windows, connected to databases, reached some critical moment that is not easily reproduceable), and you don't have to restart it after every change.

Here's an example for Common Lisp (from my cl-sqlite library):

The code:

(def-suite sqlite-suite)

(defun run-all-tests ()
  (run! 'sqlite-suite));'

(in-suite sqlite-suite)

(test test-connect
  (with-open-database (db ":memory:")))

(test test-disconnect-with-statements
    (with-open-database (db ":memory:")
      (prepare-statement db "create table users (id integer primary key, user_name text not null, age integer null)"))))

and the interactive session:

CL-USER> (sqlite-tests:run-all-tests)
 Did 7 checks.
    Pass: 7 (100%)
    Skip: 0 ( 0%)
    Fail: 0 ( 0%)

CL-USER> (defvar *db* (sqlite:connect ":memory:"))
CL-USER> (sqlite:execute-non-query *db* "create table t1 (field text not null)")
; No value
CL-USER> (sqlite:execute-non-query *db* "insert into t1 (field) values (?)" "hello")
; No value
CL-USER> (sqlite:execute-to-list *db* "select * from t1")

Now suppose that I found bug in sqlite:execute-to-list. I go to the code of this function, fix the bug and recompile this function. Then I call the fixed function and ensure that it works. The in-memory database is not gone, it has the same state as it had before recompile.

@Brian 2009-06-10 09:52:43

The name__=='__main' idiom is really nothing to do with the REPL - its a method of distinguishing between "imported as a module" and "run as a script". The code in it generally isn't the noodling and trial code you'd experiment with at the REPL, but code that you'd want to execute exactly the same repeatedly. Test code is one example, but the most common is usually to have a script that also allows reuse as a module.

@dmitry_vk 2009-06-10 15:06:14

Yes, in general, those are different things. But in context of this question, check for name was used to run (and re-run) tests, and REPL is idiomatic for such use case in lisps.

@mcandre 2011-03-07 21:14:31

The user asked for the name==main idiom, NOT a repl, NOT a test suite.

@Rainer Joswig 2009-06-10 04:33:24

In Common Lisp you can use conditional reading with features.

#+testing (run-test 'is-answer-equal-42)

Above will only be read and thus execute during load if the list of features bound to cl:*features* will contain the symbol :testing .

For example

(let ((*features* (cons :testing *features*)))
   (load "/foo/bar/my-answerlib.lisp"))

will temporarily add :testing to the list of features.

You can define your own features and control which expressions the Common Lisp system reads and which it skips.

Additionally you can also do:

#-testing (print '|we are in production mode|)

@dmitry_vk 2009-06-10 06:13:57

I don't think that features are good for this. features show the features available, not some environment state or request to run the code.

@Rainer Joswig 2009-06-10 09:10:55

why not? features used for all kinds of stuff: to describe the hardware the thing is running on, some core libs available, some modes of the software, the version of the Lisp implementation, the version of the language, whether it is :production-mode or :development-mode, etc.

@gravious 2009-06-10 04:17:37

You might want to have a look at the test-is library from clojure-contrib. It's not the same idiom, but it should support a pretty similar workflow.

@Brett Bim 2009-06-10 02:28:39

I'm very new to Clojure but I think this discussion on the Clojure groups may be a solution and/or workaround, specifically the post by Stuart Sierra on April 17th at 10:40 PM.

Related Questions

Sponsored Content

33 Answered Questions

[SOLVED] What does if __name__ == "__main__": do?

21 Answered Questions

[SOLVED] How do I check what version of Python is running my script?

  • 2009-07-07 16:17:49
  • carrier
  • 1508746 View
  • 1185 Score
  • 21 Answer
  • Tags:   python version

5 Answered Questions

[SOLVED] What is the Python 3 equivalent of "python -m SimpleHTTPServer"

22 Answered Questions

[SOLVED] What is the purpose of the word 'self'?

  • 2010-04-25 20:22:28
  • richzilla
  • 854181 View
  • 1130 Score
  • 22 Answer
  • Tags:   python class oop self

21 Answered Questions

[SOLVED] What is the use of "assert" in Python?

9 Answered Questions

[SOLVED] If Python is interpreted, what are .pyc files?

20 Answered Questions

[SOLVED] What are metaclasses in Python?

25 Answered Questions

[SOLVED] What is the Python equivalent of static variables inside a function?

  • 2008-11-10 23:33:36
  • andrewdotnich
  • 331970 View
  • 628 Score
  • 25 Answer
  • Tags:   python

Sponsored Content