Subject: Re: Lisp as a script language
From: (Rob Warnock)
Date: Mon, 21 Jun 2004 20:53:36 -0500
Newsgroups: comp.lang.lisp
Message-ID: <>
Bj�rn Lindberg <> wrote:
| Frank Buss <> writes:
| > Looks like standard CL is a bit limited, so perhaps it would be a better 
| > idea to compare a special implementation, but I don't know which is the 
| > most used implementation or the best implementation for this test.
| I suggest that you go with a specific implementation.

But remember to isolate the platform-specific stuff so you can easily
add support for more platforms later.

| Here are the first five "programs" in Clisp:

And just for fun, in CMUCL as well:

| #!/usr/bin/clisp -q
| ; Smallest running program:
| ; <empty>

As it comes "out of the box", CMUCL doesn't directly support "shebang"
style. However, there are at least three reasonable solutions:

1. Trampoline off /bin/sh (the following "exec" must be all in one line)
   on those operating systems which default to /bin/sh:

      ":" ; exec cmucl -noinit -eval "(setq *load-verbose* nil)" -load "`which $0`" ${1+"-args"} ${1+"$@"}
      ; ...your Lisp code here...

2. Use a specialized trampoline program, such as the one given here:


   which lets your script start something like this:

      #!/usr/bin/cmucl-trampoline \
      -quiet -batch -noinit
      ; ...your Lisp code here...

3. Make a little hack to "/usr/local/lib/cmucl/lib/site-init.lisp"
   [which I keep saying I'm going to post, but haven't gotten around to
   yet -- maybe this will be enough motivation] that lets you do this:

      #!/usr/local/bin/cmucl -script
      ; ...your Lisp code here...

So given one of the above, then:

| ; Hello world:
| (princ "Hello world")

Same in CMUCL.

| ; Command line arguments:
| (princ (first *args*))

  (princ (second ext:*command-line-strings*))

| ; Environment variables:
| (princ (getenv "HOME"))

Add the following routine to your startup code, then same in CMUCL:

   ;;; GETENV -- Mostly-portable code for accessing Unix
   ;;; (or Windows?) environment variables. Morphed very slightly
   ;;; from <URL:>
   ;;; Copyright (c) 2002 The Common Lisp Cookbook Project 
   ;;; See: <URL:>
   (defun getenv (name &optional default)
      #+CMU (cdr (assoc name ext:*environment-list* :test #'string=))
      #+Allegro (sys:getenv name)
      #+CLISP (ext:getenv name)
      #+ECL (si:getenv name)
      #+SBCL (sb-unix::posix-getenv name)
      #+LISPWORKS (lispworks:environment-variable name)

| ; Return non-zero exit code when file does not exist:
| (unless (probe-file "/etc/mtab") (exit 1))

Same in CMUCL, except use (QUIT 1) instead of (EXIT 1).

Also, see the function EXT:RUN-PROGRAM to see how to run programs
from within CMUCL. E.g., in the simple case where we just want to
run a sub-process, get its output on stdout, and wait for it to exit,
given the following definition:

   (defun system (command-string)
     (let ((proc (run-program "/bin/sh" (list "-c" command-string)
			      :wait t :input t :output t :error t)))
       (prog1 (process-exit-code proc) (process-close proc))))

you can then do this:

   > (system "ls -l foo*.[0-9]")
   -rw-r--r--  1 rpw3  rpw3   5361 Mar 30 13:40 foo.1
   -rw-r--r--  1 rpw3  rpw3   4504 Apr 14 22:57 foo.2
   -rw-r--r--  1 rpw3  rpw3   6211 Apr 14 23:01 foo.3
   -rw-r--r--  1 rpw3  rpw3  55971 Apr 14 23:04 foo.4

   > (system "ls -l foo3*")
   ls: foo3*: No such file or directory



Rob Warnock			<>
627 26th Avenue			<URL:>
San Mateo, CA 94403		(650)572-2607