From: Burton Samograd
Subject: evalquote repl?
Date: 
Message-ID: <87bqu2apww.fsf@gmail.com>
Hi,

I'm curious about the evalquote lisp syntax/style and was wondering if
there might be any information (google turns up little) or possibly a
CL implimentation of a repl loop that could be used or ported to
CMUCL/SBCL.

TIA.

-- 
burton samograd					kruhft .at. gmail
kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com

From: Tel A.
Subject: Re: evalquote repl?
Date: 
Message-ID: <1147540917.746463.226210@y43g2000cwc.googlegroups.com>
> CL implimentation of a repl loop that could be used or ported to
> CMUCL/SBCL.

These implementations already come with a repl that is indeed their
standard interaction mode. Just fire one up on the command line.

Otherwise, if you're interested in the basis of a repl, a simple one
could be the following:

(loop (format t "~&~A~%" (eval (read))))

If you realize that format is just a romanticized print that makes
things easier to read and read that form inside out you get Read, Eval,
Print, Loop.

The actual repls used in lisp implementations are more involved, of
course. For instance, error checking can be built in before the eval
which ensures that a debugger function catches badly formed inputs
before they could potentially break the loop.
From: Burton Samograd
Subject: Re: evalquote repl?
Date: 
Message-ID: <87r72xerpb.fsf@gmail.com>
"Tel A." <············@gmail.com> writes:

>> CL implimentation of a repl loop that could be used or ported to
>> CMUCL/SBCL.
>
> These implementations already come with a repl that is indeed their
> standard interaction mode. Just fire one up on the command line.
>
> Otherwise, if you're interested in the basis of a repl, a simple one
> could be the following:
>
> (loop (format t "~&~A~%" (eval (read))))
>
> If you realize that format is just a romanticized print that makes
> things easier to read and read that form inside out you get Read, Eval,
> Print, Loop.
>
> The actual repls used in lisp implementations are more involved, of
> course. For instance, error checking can be built in before the eval
> which ensures that a debugger function catches badly formed inputs
> before they could potentially break the loop.

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))

before performing the actual evaluation.  I'm interested in that type
of system and was wondering if there was a source implimentation
available to look at.

-- 
burton samograd					kruhft .at. gmail
kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com
From: Pascal Bourguignon
Subject: Re: evalquote repl?
Date: 
Message-ID: <87wtcp4mbe.fsf@thalassa.informatimago.com>
Burton Samograd <······@gmail.com> writes:

> "Tel A." <············@gmail.com> writes:
>
>>> CL implimentation of a repl loop that could be used or ported to
>>> CMUCL/SBCL.
>>
>> These implementations already come with a repl that is indeed their
>> standard interaction mode. Just fire one up on the command line.
>>
>> Otherwise, if you're interested in the basis of a repl, a simple one
>> could be the following:
>>
>> (loop (format t "~&~A~%" (eval (read))))
>>
>> If you realize that format is just a romanticized print that makes
>> things easier to read and read that form inside out you get Read, Eval,
>> Print, Loop.
>>
>> The actual repls used in lisp implementations are more involved, of
>> course. For instance, error checking can be built in before the eval
>> which ensures that a debugger function catches badly formed inputs
>> before they could potentially break the loop.
>
> 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))
>
> before performing the actual evaluation.  I'm interested in that type
> of system and was wondering if there was a source implimentation
> available to look at.

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)

than:

   (eval (cons operator (mapcar (lambda (arg) (list (quote quote) arg))
                                arguments)))

See section 2.2.1, page 4 of:
http://www.dreamsongs.com/NewFiles/Hopl2.pdf 



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
From: Rob Warnock
Subject: Re: evalquote repl?
Date: 
Message-ID: <5aCdnRJPsLYTAvvZnZ2dnUVZ_vudnZ2d@speakeasy.net>
Pascal Bourguignon  <···@informatimago.com> wrote:
+---------------
| Burton Samograd <······@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.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Burton Samograd
Subject: Re: evalquote repl?
Date: 
Message-ID: <87wtcpthar.fsf@gmail.com>
····@rpw3.org (Rob Warnock) writes:

> Pascal Bourguignon  <···@informatimago.com> wrote:
> +---------------
<snip>
> 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:

Yes, that is closer that what I was looking for.  You metion TCL, but
I was thinking more of shell script (Bourne).  I've been looking at
Haskell for a while and find it's lazy properties interesting, and
have found the non-evaluation (or forced evaluation with the $
keychar) properties of sh quite interesting.  I ran across the
EVALQUOTE paper a while back and it reminded me of what sh was,
although I've never really saw how it worked in practice (and hence my
post :).  I was thinking that using the implicit argument quoting of
EVALQUOTE with a macro character mapped to EVAL (like, maybe, $), you
could have something that looks a bit more like shell script, but also
features lazyish/implicit evaluation to play with.  

Why on earth would I want that? I don't know, it just sounds kinda
cool.  Thanks for the answers and example code; I'll see what I can do
with it in the future.

-- 
burton samograd					kruhft .at. gmail
kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com
From: Pascal Bourguignon
Subject: Re: evalquote repl?
Date: 
Message-ID: <878xp561mb.fsf@thalassa.informatimago.com>
Burton Samograd <······@gmail.com> writes:
> I'm curious about the evalquote lisp syntax/style and was wondering if
> there might be any information (google turns up little) or possibly a
> CL implimentation of a repl loop that could be used or ported to
> CMUCL/SBCL.

As mentionned by "Tel A.", all known Common Lisp implementation comes
with a REPL. http://www.lispworks.com/documentation/HyperSpec/Body/25_aa.htm

You can write your own REPL, implementing these specifications, as follow:

(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* "~&"))
     (condition 
         (ERR) 
       (format *error-output* "~&~A: ~%  ~S~%"
               (class-name (class-of err)) err))))

(defun repl ()
  (do ((+eof+ (gensym))
       (hist 1 (1+ hist)))
      (nil)
    (format t "~%~A[~D]> " (package-name *package*) hist)
    (handling-errors
     (setf - (read *standard-input* nil +eof+))
     (when (or (eq - +eof+)
               (member - '((quit)(exit)(continue)) :test (function equal)))
       (return-from repl))
     (let ((results (multiple-value-list (eval -))))
       (setf +++ ++   ++ +   + -
             /// //   // /   / results
             *** **   ** *   * (first /)))
     (format t "~& --> ~{~S~^ ;~%     ~}~%" /))))


But this is a MacLisp like REPL, using EVAL, instead of
EVALQUOTE. There's no EVALQUOTE in Common Lisp, but you can as easily
write an EVALQUOTE REPL:

(defun reqpl ()
  (do ((+eof+ (gensym))
       (hist 1 (1+ hist)))
      (nil)
    (format t "~%~A[~D]EVALQUOTE> " (package-name *package*) hist)
    (handling-errors
     (let ((operator  (read *standard-input* nil +eof+)))
       (if (member operator '(quit exit continue) :test (function equal))
           (return-from reqpl)
           (let ((arguments (read *standard-input* nil +eof+)))
             (cond
               ((or (eq operator +eof+) (eq arguments +eof+)) 
                (setf - +eof+))
               ((and (fboundp operator)
                     (not (macro-function operator))
                     (not (special-operator-p operator)))
                (setf - (cons operator
                              (mapcar (lambda (arg) `(quote ,arg)) arguments))))
               ((and (fboundp operator)
                     (or (macro-function operator)
                         (special-operator-p operator)))
                (setf - (cons operator arguments)))
               (t
                (error "~A is not an operator" operator))))))
     (when (eq - +eof+) (return-from reqpl))
     (let ((results (multiple-value-list (eval -))))
       (setf +++ ++   ++ +   + -
             /// //   // /   / results
             *** **   ** *   * (first /)))
     (format t "~& --> ~{~S~^ ;~%     ~}~%" /))))


But this is harder to use, in particular to get the value of the variables:

[10]> (reqpl)

COMMON-LISP-USER[1]EVALQUOTE> +(1 2 3)
 --> 6

COMMON-LISP-USER[2]EVALQUOTE> print(+)

+ 
 --> +

COMMON-LISP-USER[3]EVALQUOTE> eval((print ++))

(+ '1 '2 '3) 
 --> (+ '1 '2 '3)

COMMON-LISP-USER[4]EVALQUOTE> defvar(*v* (+ 2 3 4))
 --> *V*

COMMON-LISP-USER[5]EVALQUOTE> print(*v*)

*V* 
 --> *V*

COMMON-LISP-USER[6]EVALQUOTE> eval((print *v*))

9 
 --> 9

COMMON-LISP-USER[7]EVALQUOTE> eval((print +++))

(DEFVAR *V* (+ 2 3 4)) 
 --> (DEFVAR *V* (+ 2 3 4))

COMMON-LISP-USER[8]EVALQUOTE> quit
NIL

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush