Scheme-scripts suffer from two drawbacks:
The following approach solves these problems at the expense of slower
startup. Make ‘#! /bin/sh’ the first line and prepend every
subsequent line to be executed by the shell with
:;. The last
line to be executed by the shell should contain an exec command;
exec tail-calls its argument.
/bin/sh is thus invoked with the name of the script file, which
it executes as a *sh script. Usually the second line starts
‘:;exec scm -f$0’, which executes scm, which in turn loads the
script file. When SCM loads the script file, it ignores the first and
second lines, and evaluates the rest of the file as Scheme source code.
The second line of the script file does not have the length restriction
mentioned above. Also,
/bin/sh searches the directories listed
in the ‘PATH’ environment variable for ‘scm’, eliminating the need
to use absolute locations in order to invoke a program.
The following example additionally sets *script* to the script argument, making it compatible with the scheme code of the previous example.
#! /bin/sh :;exec scm -e"(set! *script* \"$0\")" -l$0 "$@" (define (fact.script args) (cond ((and (= 1 (length args)) (string->number (car args))) => (lambda (n) (print (fact n)) #t)) (else (fact.usage)))) (define (fact.usage) (print *argv*) (display "\ Usage: fact N Returns the factorial of N. " (current-error-port)) #f) (define (fact n) (if (< n 2) 1 (* n (fact (+ -1 n))))) (if *script* (exit (fact.script (list-tail *argv* *optind*))))
./fact 6 ⇒ 720