4

I wrote two functions in two separated files, assumed to be file A.lisp and B.lisp, where both files have some main program code for test and A.lisp would call the function in B.lisp. This means using the load method directly in A.lisp would execute the main code in B.lisp, which is not supposed to happen. And these files are, in my opinion, too small to be considered using something like package.

Is there anything like Python's if __name__ == "__main__": stuff in Common Lisp? Top-level code that's wrapped inside this condition will only be executed if the current file is the main module, i.e. the running program, but not if it's imported as a library.

Rörd
  • 6,556
  • 21
  • 27
lastland
  • 890
  • 3
  • 14
  • 28
  • I asked [a similar question about Clojure](http://stackoverflow.com/questions/973106/what-is-the-clojure-equivalent-of-the-python-idiom-if-name-main), rather than Common Lisp, but you might find some of responses helpful, especially the one which is currently top-rated. – Tim Gilbert Jun 20 '13 at 21:12

4 Answers4

6

Packages are only namespaces for symbols. They don't say anything about loading or compiling code.

Common Lisp does not have the idea of a library, module or even something like a 'main' module/routine in its ANSI Common Lisp standard. The standard defines two routines PROVIDEand REQUIRE. But those are not very well specified.

Most applications and libraries use a 'system' tool to structure, specify, compile and load code.

There is a 'free' one called ASDF. 'Another System Definition Facility'. For most types of applications a tool like ASDF is useful. For primitive applications you can write your own tools using standard functions like COMPILE-FILEand LOAD.

Nick Levine wrote a tutorial for ASDF (part of his abandoned Lisp book project): Systems.

Several Lisp implementations have more extensive facilities to create applications (for example Mac OS X applications written with Clozure Common Lisp).

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
4

The if __name__ == "__main__": idiom is very specific to Python, and even some people in the Python community consider using it for test code bad style.

With Common Lisp's high emphasis on interactive development in the REPL, it would actually be a disadvantage to have to reload the whole file each time you want to run the tests. Just put the tests into a function definition instead of the top level, it works and is more convenient.

Rörd
  • 6,556
  • 21
  • 27
  • So there's no way to write code that is executed only when I run the file with `clisp myfile.lisp` and not `(load 'myfile)`? – zstewart Oct 28 '15 at 18:56
  • You could put the code that you only want to be evaluated when running the file as a script into a special function that you call from the command line when evaluating the script. I only have SBCL rather than CLISP installed, so I can't test how exactly you would need to do this with CLISP, with SBCL you could do `sbcl --noinform --load myfile.lisp --eval '(main)' --quit` which is of course a good deal longer than the `sbcl --script myfile.lisp` that you can do when the code is at the top-level. So the easier way would be to just make the script an extra file that loads the library part. – Rörd Oct 28 '15 at 21:21
2

Top level forms are evaluated.

You could define a main function as in the following example, and you could call that function whatever you like:

a.lisp:

(defun main ()
  ...)

b.lisp:

(load "a.lisp")
(main)
sbenitezb
  • 536
  • 7
  • 21
  • But what if I want to run A.lisp alone sometimes for some testing work? – lastland Jan 03 '12 at 14:36
  • But I have to be able to execute the main function in A.lisp if I want to execute it alone. How can I do this if the function call of main only exists in B.lisp? – lastland Jan 03 '12 at 15:10
  • 1
    Wouldn't it be sufficient to create a specific function for each .lisp file that runs the tests you want, such as _run-a-tests_ and _run-b-tests_ and then you call that function from the REPL? Or are you running it as a script from a shell? – sbenitezb Jan 03 '12 at 15:33
  • Running things as scripts from a shell is a pretty normal operating mode. If I have some code to run as the "main" action of executing a file, it is convenient to just tell lisp to run that file, but if I want to debug in the REPL, it is convenient to be able to load the file without executing the "main" action. Its a lot more convenient to keep these two things together and use something like `if __name__ == '__main__':` than create a second file that just loads the first and activates the "main" action. – zstewart Oct 28 '15 at 18:51
1

I don't really know how it works in Python but it looks like a file is a module, and two files are two distinct modules. This not the case in Common Lisp. If you don't define any package, when you load a file, all definitions will be available in the current package (CL-USER is the default). It's more like if you've pasted your code into the REPL.

But packages aren't really hard to use.

in A.lisp:

(defpackage foo
  (:use #:cl)
  (:export main))

(in-package :foo)

(defun main ()
   (do-some-stuff)
   (baz:main some-args))

in B.lisp:

(defpackage baz
  (:use #:cl)
  (:export main))

(in-package :baz)

(defun main (some-args)
   (do-some-stuff))

You could read The Complete Idiot's Guide to Common Lisp Packages and PCL chapter on packages.

Daimrod
  • 4,902
  • 23
  • 25