Haskell's main
function does just what I want: evaluate when the file is loaded by itself (e.g. ./myfile.hs
or runhaskell myfile.hs
) and in no other case. main
will not be called when the file is imported by another file. newLISP also has this functionality.
Is there equivalent code for Common Lisp?
I read the source code for CLISP. Here's what happens when the user enters clisp myfile.lisp
or ./myfile.lisp
:
myfile.lisp
as p->argv_execute_file
.(LOAD "p->argv_execute_file")
and pushes it onto the Lisp stack.*args*
.CLISP never makes a Lisp variable referring to p->argv_execute_file
, so there is no way to discern whether myfile.lisp
was loaded directly, by the user in the REPL, or by another Lisp file. If only (car *args*)
were myfile.lisp
, my task would be easy.
Note: Shebangs give CLISP trouble if the file is loaded from the REPL, so I put this code in ~/.clisprc.lisp
:
(set-dispatch-macro-character #\# #\!
(lambda (stream character n)
(declare (ignore character n))
(read-line stream nil nil t)
nil))
I found a solution. It's a bit of shell trickery, but it works. I'll soon modify this to work on CL implementations other than CLISP.
#!/bin/sh
#|
exec clisp -q -q $0 $0 ${1+"$@"}
exit
|#
;;; Usage: ./scriptedmain.lisp
(defun main (args)
(format t "Hello World!~%")
(quit))
;;; With help from Francois-Rene Rideau
;;; http://tinyurl.com/cli-args
(let ((args
#+clisp ext:*args*
#+sbcl sb-ext:*posix-argv*
#+clozure (ccl::command-line-arguments)
#+gcl si:*command-args*
#+ecl (loop for i from 0 below (si:argc) collect (si:argv i))
#+cmu extensions:*command-line-strings*
#+allegro (sys:command-line-arguments)
#+lispworks sys:*line-arguments-list*
))
(if (member (pathname-name *load-truename*)
args
:test #'(lambda (x y) (search x y :test #'equalp)))
(main args)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With