Subject: Re: evalquote repl?
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 13 May 2006 22:10:06 -0500
Newsgroups: comp.lang.lisp
Message-ID: <5aCdnRJPsLYTAvvZnZ2dnUVZ_vudnZ2d@speakeasy.net>
Pascal Bourguignon  <pjb@informatimago.com> wrote:
+---------------
| Burton Samograd <kruhft@gmail.com> writes:
| > Sorry, maybe I wasn't being clear enough.  I'm actually looking for a
| > specific kind of repl, one which was used on systems like the
| > Interlisp, which was of the type evalquote.  It basically inserted the
| > outer parenthesis on the command that was typed and automatically
| > quoted the arguments for you.  It took something like this:
| >   print (1 2 3)
| > and converted it into this:
| >   (print '(1 2 3))
| 
| No, this is not the transformation that was done. It was:
|   print(1 2 3) --> (print '1 '2 '3)
| Well, actually it didn't need to do this transformation.
|  Contrarily to my implementation, it was more like:
|    (apply operator arguments)
...
| See section 2.2.1, page 4 of: http://www.dreamsongs.com/NewFiles/Hopl2.pdf 
+---------------

Indeed. And as it says in that paper:

    The "quote" in the name EVALQUOTE signifies the "implicit quoting
    of the arguments" to the function applied. MacLisp forked off
    and used EVAL exclusively as a top level interface, while BBNLisp
    (and thus Interlisp) accommodated both, using EVAL if the input
    was one form and APPLY if the input line was two or more forms.

Something like the latter could be done in CL like this
[caveat: no error handling!]:

    (loop
      (format t "~&prompt> ")
      (force-output)
      (let ((forms (loop for form = (read-preserving-whitespace)
                         collect form
                         until (eql (peek-char) #\newline))))
        (format t "~&~{~S~%~}" (multiple-value-list 
                                (if (endp (cdr forms))
                                  (eval (car forms))   
                                  (apply (car forms) (cdr forms)))))))
 
Examples:

    prompt> (+ 1 2 3)

    6
    prompt> + 1 2 3

    6
    prompt> (defun double (x) (* 2 x))

    DOUBLE
    prompt> double 4

    8
    prompt> mapcar double (1 3 5)

    (2 6 10)
    prompt> values foo bar baz

    FOO
    BAR
    BAZ
    prompt> (apply 'values (mapcar 'double '(1 3 5)))

    2
    6
    10
    prompt> 

Unfortunately, I'm not sure how to [or if one even can!] get that
latter one to work in the EVALQUOTE style.

+---------------
| > It basically inserted the outer parenthesis on the command that
| > was typed and automatically quoted the arguments for you.
+---------------

A slightly different style [and IMHO much more useful] which I have
written about here before several times in the context of CLI utilities
for the parenthephobic, is what I call the OPFR ["Outer-Parentheses-
Free Repl"] style. Like the dual-mode EVAL/EVALQUOTE loop shown above,
it either does a plain EVAL or else gathers items READ from the input
until terminated by an unescaped newline. Unlike EVALQUOTE, though,
the arguments *are* evaluated in normal Lisp style (instead of being
quoted). This give a look that's almost "Tcl-like" provided that only
pre-defined functions are called with literal args, yet the full power
of CL is available when needed:

    opfr> expt 2 64
    18446744073709551616
    opfr> format t "x=~a, y=~a~%" 123 456
    x=123, y=456
    nil
    opfr> + 1 2 3
    6
    opfr> mapcar 'sqrt '(1 2 3)
    (1.0 1.4142135 1.7320508)
    opfr> defun double (x) (* 2 x)
    DOUBLE
    opfr> apply 'values (mapcar 'double '(1 3 5))
    2
    6
    10
    opfr> loop for i to 4 \
	       for j = (expt 2 i) \
	   collect (list
		    i
		    j
		    (+ i j)
		    (* i j))
    ((0 1 1 0) (1 2 3 2) (2 4 6 8) (3 8 11 24) (4 16 20 64))
    opfr> (let ((x 2) (y 3))  ; And, yes, it accepts normal s-exprs too
	    (apply 'values (mapcar '* (list x y))))
    2
    3
    opfr> 

The function OPFR-REPL is left as an exercise for the reader.
[At least, until I get around to posting a cleaned-up version.]  ;-}


-Rob

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