
Michael Price writes:
On 8/24/06, Marco Antoniotti <marcoxa@cs.nyu.edu> wrote:
Hi
I would like to suggest a feature for SLIME taken from Lispworks.
In LW I can type
prompt> member 42 '((3 2 3) (1 42 33) (42 11 22)) :key #'second ((1 42 33) (42 11 22))
I.e. a line gets parenthesized if it is not already an expression (of course there are cases where things get hairy, but in general I find it useful).
CL-USER> (defvar a 4)
A CL-USER> (defvar b 9)
B CL-USER> a b
4 CL-USER> 9 CL-USER> (defun a (x) (sqrt x))
A CL-USER> (a b)
3.0
So what happens in lispworks if I do this:
CL-USER> a b
Do I get a separate 4 and 9 again or do I get 3.0?
Well, you can still get the variables with list or values: (defmacro handling-errors (&body body) `(HANDLER-CASE (progn ,@body) (simple-condition (ERR) (format *error-output* "~&~A: ~%" (class-name (class-of err))) (apply (function format) *error-output* (simple-condition-format-control err) (simple-condition-format-arguments err)) (format *error-output* "~&") (finish-output)) (condition (ERR) (format *error-output* "~&~A: ~% ~S~%" (class-name (class-of err)) err) (finish-output)))) (defun line-repl () (do ((+eof+ (gensym)) (hist 1 (1+ hist))) (nil) (format t "~%~A[~D]LINE> " (package-name *package*) hist) (finish-output) (handling-errors (let ((operator (read *standard-input* nil +eof+))) (if (member operator '(quit exit continue) :test (function equal)) (return-from line-repl) (let ((arguments (read-line *standard-input* nil +eof+))) (if (eql arguments +eof+) (return-from line-repl) (setf - (read-from-string (format nil "(~A ~A)" operator arguments)))))) (let ((results (multiple-value-list (eval -)))) (setf +++ ++ ++ + + - /// // // / / results *** ** ** * * (first /))) (format t "~& --> ~{~S~^ ;~% ~}~%" /) (finish-output))))) [61]> (line-repl) COMMON-LISP-USER[1]LINE> defvar a 3 --> A COMMON-LISP-USER[2]LINE> defvar b 6 --> B COMMON-LISP-USER[3]LINE> defun a () 3.14 --> A COMMON-LISP-USER[4]LINE> a --> 3.14 COMMON-LISP-USER[5]LINE> defun a (x) (* 3.0 x) --> A COMMON-LISP-USER[6]LINE> a b --> 18.0 COMMON-LISP-USER[7]LINE> list a b --> (1 6) COMMON-LISP-USER[8]LINE> values a b --> 1 ; 6 COMMON-LISP-USER[9]LINE> quit NIL [62]> Using an implementation dependant function such as #+clisp EXT:ARGLIST you can even read the first token, see if it's a function, get the argument list expected for the function and further parse the number of sub expressions needed. You can even do it recursively, to parse correctly expressions such as: append cons car items cddr items cons parse-integer "123" :radix 5 nil to: (append (cons (car items) (cddr items)) (cons (parse-integer "123" :radix 5) nil)) The limit goes when you want to use functions with &REST: list + 1 2 3 - 4 5 * 6 7 0 is totally ambiguous. For &rest, you have to reintroduce parentheses, or at least an end of list mark: list + 1 2 3) - 4) 5 * 6 7 0 can then be parsed as: (list (+ 1 2 3) (- 4) 5 (* 6 7 0)) while: list + 1 2 3 - 4 5)) * 6 7 0 can then be parsed as: (list (+ 1 2 3 (- 4 5)) (* 6 7 0)) You still have a problem with lisp-2 ambiguous symbols: cons car list 2 3 could be either: (cons (car list) 2) 3 (cons (car (list 2)) 3) (cons (car (list 2 3))) If we assume we have all the input before parsing it, we can still resolve some of these ambiguities (only the second one would be a correct single form), but there could remain a lot of unresolvable cases. Parentheses are a necessity in lisp-2 with &rest. -- __Pascal Bourguignon__ http://www.informatimago.com/ CAUTION: The mass of this product contains the energy equivalent of 85 million tons of TNT per net ounce of weight.