Subject: Re: Problems executing from command line
From: rpw3@rpw3.org (Rob Warnock)
Date: Mon, 12 Jan 2004 04:46:19 -0600
Newsgroups: comp.lang.lisp
Message-ID: <MaydnSSDjNNm55_dRVn-ig@speakeasy.net>
Greg Zancewicz <zancewicz@alum.mit.edu> wrote:
+---------------
| I am running CMUCL on Red Hat Linux 9.0.  I am trying to figure out how to
| run LISP programs from the shell or at least evaluate expressions. 
| According to the man pages "lisp -eval <expr>" should work, but when I try
| something simple - like "lisp -eval '(+ 1 2)'" LISP comes up without any
| error, but I don't get any output from my expression.
| 
| Anyone have any ideas what I am doing wrong? ...
+---------------

As another poster said, you forgot to PRINT the result.

FWIW, I have a little shell script called "cmu" which when run without
arguments just gives a REPL (with "my usual conveneniences" loaded), but
when run *with* one or more arguments concatenates them and read/eval/prints
them (including handling multiple values) and then exits. Aliased to the
name "=" [yes, that *is* a legal Unix command name!], it becomes a handy-
dandy Lisp "calculator" for one-liners:  ;-}  ;-}

	% = + 123 456
	579
	% = + 123 '(* 57 8)'
	579
	% = floor 12345 678
	18
	141
	% = loop for i below 3 collect i
	(0 1 2)
	% = apply "#'values" '(loop for i below 3 collect i)'
	0
	1
	2
	% = expt 2 100
	1267650600228229401496703205376
	% = expt 2 200
	1606938044258990275541962092341162602522202993782792835301376
	% = get-universal-time
	3282892657
	% = file-write-date '"foo"'
	3282551003
	% = format-universal-time nil '(file-write-date "foo")' :style :iso8601
	"Thu, 2004-01-08 03:43:23-08:00"
	%

Note: As a convenience [arguably ugly, but personally I find it very handy
for shell-level use], single args which are symbols that are FBOUNDP are
*called* with no args;
other single arguments (literals or variables) just have their values
printed. Multiple args are always consed into a list and evaluated (and
thus the first arg is assumed to be a function).

Source code for the interesting part [trimmed of a bunch of personal hacks]:

	":" ; exec cmucl -noinit -eval "(setq *load-verbose* nil)" -load "`which $0`" ${1+"-args"} ${1+"$@"}
	;;; The above trampoline depends on the operating system using
	;;; /bin/sh (or equiv.) as the interpreter when an executable script
	;;; *doesn't* start with "#!", but avoids requiring a reader macro
	;;; for "#!" in the CMUCL image.

	...other stuff here [REQUIREs, etc.]...

	(defvar *script-interactive-repl* nil)  ; NIL, so one-liners exit.
	(defvar *script-args* (get-command-line-switch "args"))

	(defun mv-eval-print (form)
	  (format t "~{~S~%~}" (multiple-value-list (eval form))))

	(let ((args (mapcar #'read-from-string *script-args*)))
	  (case (length args)
	    ;; No args, just start normal (well, slightly-customized) REPL.
	    ((0) (setf *script-interactive-repl* t) ; Magic flag.
		 ;; Pick up other conveniences (not done automatically,
		 ;; since we ran this "-noinit".
		 (load "home:.cmucl-init"))
	    ;; In the single-arg case, do a convenient-but-oh-so-ugly hack
	    ;; of checking to see if the arg is a defined function, and if so,
	    ;; call it instead of printing the special var of that name.
	    ((1)
	     (let ((arg (car args)))
	       (if (and (symbolp arg) (fboundp arg))
		 (mv-eval-print args)
		 (mv-eval-print arg))))
	    ;; Multiple args, cons a list of them.
	    (t (mv-eval-print args))))

	(unless *script-interactive-repl*
	  (unix:unix-exit))

	;;; Fall into REPL...

Hope this is helpful...


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607