perm filename CLITER.MSG[COM,LSP]4 blob sn#781410 filedate 1985-01-02 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	Introduction
C00004 ENDMK
C⊗;
Introduction
Welcome to the Common Lisp Iteration Subgroup.
In order to mail to this group, send to the address:

		CL-Iteration@su-ai.arpa

Capitalization is not necessary, and if you are directly on the ARPANET,
you can nickname SU-AI.ARPA as SAIL. An archive of messages is kept on
SAIL in the file:

			   CLITER.MSG[COM,LSP]

You can read this file or FTP it away without logging in to SAIL.

To communicate with the moderator, send to the address:

		CL-Iteration-request@su-ai.arpa

Here is a list of the people who are currently on the mailing list:

Person			Affiliation	Net Address

Kent Pitman		MIT		kmp@mc
David Wile		ISI		Wile@ISI-VAXA
Eric Benson		Lucid		eb@su-ai
Bob Kessler		Univ. of Utah	kessler@utah-20
Bob Kerns		Symbolics	rwk@mc
David Moon		Symbolics	moon@scrc-stonybrook
Guy Steele		Tartan		steele@tl-20a

The first order of business is for each of us to ask people we know who may
be interested in this subgroup if they would like to be added to this list.

Next, we ought to consider who might wish to be the chairman of this subgroup.
Before this happens, I think we ought to wait until the list is more nearly
complete. 

∂23-Sep-84  1613	RPG  	Introduction  
To:   CL-iteration@SU-AI.ARPA    
Welcome to the Common Lisp Iteration Subgroup.
In order to mail to this group, send to the address:

		CL-Iteration@su-ai.arpa

Capitalization is not necessary, and if you are directly on the ARPANET,
you can nickname SU-AI.ARPA as SAIL. An archive of messages is kept on
SAIL in the file:

			   CLITER.MSG[COM,LSP]

You can read this file or FTP it away without logging in to SAIL.

To communicate with the moderator, send to the address:

		CL-Iteration-request@su-ai.arpa

Here is a list of the people who are currently on the mailing list:

Person			Affiliation	Net Address

Kent Pitman		MIT		kmp@mc
David Wile		ISI		Wile@ISI-VAXA
Eric Benson		Lucid		eb@su-ai
Bob Kessler		Univ. of Utah	kessler@utah-20
Bob Kerns		Symbolics	rwk@mc
David Moon		Symbolics	moon@scrc-stonybrook
Guy Steele		Tartan		steele@tl-20a

The first order of business is for each of us to ask people we know who may
be interested in this subgroup if they would like to be added to this list.

Next, we ought to consider who might wish to be the chairman of this subgroup.
Before this happens, I think we ought to wait until the list is more nearly
complete. 

∂02-Oct-84  1313	RPG  	Chairman 
To:   cl-iteration@SU-AI.ARPA    
Now that we've basically got most everyone who is interested on the mailing
list, let's pick a chairman. I suggest that people volunteer for chairman.

The duties are to keep the discussion going, to gather proposals and review
them, and to otherwise administer the needs of the mailing list. I will
retain the duties of maintaining the list itself and the archives, but
otherwise the chairman will be running the show. 

Any takers?
			-rpg-

∂13-Oct-84  1443	RPG  	Chairman 
To:   cl-iteration@SU-AI.ARPA    

Guy Steele has been nominated as chairman of the Iteration
subgroup.  If he is willing, and no one else volunteers, he will
become chairman. Please respond by October 24. At the end of this month
I want to see some ideas and proposals coming in on this mailing list.
			-rpg-

∂02-Nov-84  1020	RPG   	Re: Iteration
 ∂29-Oct-84  0633	STEELE@TL-20A.ARPA 	Re: Iteration  
Received: from TL-20A.ARPA by SU-AI.ARPA with TCP; 29 Oct 84  06:33:07 PST
Received: ID <STEELE@TL-20A.ARPA.#Internet>; Mon 29 Oct 84 09:32:39-EST
Date: Mon 29 Oct 84 09:32:36-EST
From: STEELE@TL-20A.ARPA
Subject: Re: Iteration
To: RPG@SU-AI.ARPA
cc: STEELE@TL-20A.ARPA
In-Reply-To: Message from "Dick Gabriel <RPG@SU-AI.ARPA>" of Sat 27 Oct 84 22:03:00-EDT

I suppose I could chair the iteration subgroup, but here is my position.
I don't feel that any additional peculiar iteration syntax is needed.
If no one else feels the need for it strongly enough to want to chair
the subgroup, then the whole thing might as well quietly disappear by
reason of apathy.
--Q
-------

∂10-Dec-84  0757	STEELE@TL-20A.ARPA 	[CL.BOYER@UTEXAS-20.ARPA: loop & defmacro]   
Received: from TL-20A.ARPA by SU-AI.ARPA with TCP; 10 Dec 84  07:53:45 PST
Received: ID <STEELE@TL-20A.ARPA.#Internet>; Mon 10 Dec 84 10:54:52-EST
Date: Mon 10 Dec 84 10:54:51-EST
From: STEELE@TL-20A.ARPA
Subject: [CL.BOYER@UTEXAS-20.ARPA: loop & defmacro]
To: cl-iteration@SU-AI.ARPA

Return-Path: <@TL-20B.ARPA:CL.BOYER@UTEXAS-20.ARPA>
Received: from TL-20B.ARPA by TL-20A.ARPA with TCP; Sun 9 Dec 84 17:41:26-EST
Received: from UTEXAS-20.ARPA by TL-20B.ARPA with TCP; Sun 9 Dec 84 17:40:40-EST
Date: Sun, 9 Dec 1984  16:38 CST
From: CL.BOYER@UTEXAS-20.ARPA
To:   steele@tartan
Cc:   rpg@su-ai, hedrick@rutgers
Subject: loop & defmacro

Since RPG named you as moderator of the "iteration/loop" subgroup
I haven't seen any mail on the subject.  Has there been any?

In my opinion, LOOP is pretty good as it is and should be
adopted as part of Common Lisp.  If I had my way, I would
add to it something that was subtracted from the Interlisp
I.S.OPR when LOOP was coded, namely the ability to add more
I.S.OPRS.  For example, I now write in Zetalisp:

     (loop for x in l with ans = 0
	   do (setq ans (logor x ans))
	   finally (return ans))

where I would like to write

     (loop for x in l logor x).  

I used to be able to write something like that in Interlisp,
which has a facility for defining the initial, iterative,
and final action of a new "quantifier" such as logor.
Anyway, that's my 2-bits worth.

Finally, and totally unrelatedly, is it true that

     (defmacro foo x ...)

is not permited in Common Lisp and that
I need to write

     (defmacro foo (&whole x) ...)?

I'm trying to find some common ground with psl and the maclisp
dialects, but it doesn't look like there is a general
purpose intersection.  As I read it, a lambda list has
to be a list, and that excludes a symbolp.

P.S. Hedrick's 2060 Common Lisp permits (defmacro foo x ...).

Thanks,

Bob
-------

∂10-Dec-84  0805	STEELE@TL-20A.ARPA 	Reply to Boyer 
Received: from TL-20A.ARPA by SU-AI.ARPA with TCP; 10 Dec 84  08:04:59 PST
Received: ID <STEELE@TL-20A.ARPA.#Internet>; Mon 10 Dec 84 11:06:02-EST
Date: Mon 10 Dec 84 11:05:59-EST
From: STEELE@TL-20A.ARPA
Subject: Reply to Boyer
To: cl-iteration@SU-AI.ARPA

I was nominated to moderate the iteration subgroup, but declined the
nomination, on the following grounds: my own preference is for the
status quo, as I have not yet seen any LOOP syntax I can comfortably
endorse.  Therefore I am waiting for another to step forward to
moderate; and if no one does, that would indicate to me that no one
else really wants the LOOP syntax either.

What you would write as
	(for x in l logor x)
I would write as
	(reduce #'logor l)
This is of course not a general argument against LOOP, but the existence
of general mapping and reduction operators in Common LISP should not
be overlooked.

You are correct in stating that Common Lisp does not permit
	(defmacro foo x ...)
More precisely, a valid Common LISP program may not use such
a construct and expect to be portable.  A Common LISP implementation
may, if it wished, support that syntax as a (non-portable)
extension.
--Guy
-------

∂10-Dec-84  1010	SHEBS@UTAH-20.ARPA 	Misc 
Received: from UTAH-20.ARPA by SU-AI.ARPA with TCP; 10 Dec 84  10:10:11 PST
Date: Mon 10 Dec 84 11:11:17-MST
From: Stan Shebs <SHEBS@UTAH-20.ARPA>
Subject: Misc
To: cl-iteration@SU-AI.ARPA

I would volunteer to moderate if my stature weren't so low...

First off, I don't believe that the status quo is necessarily desirable.
Personally, I like the PSL FOR macro with its more Lispy syntax - the
more complex iterations are easier to read when there's lots of parens.
Editors that understand parens also do a better job of formatting.
Unfortunately, The Book appears to exclude such a format by requiring
that LOOP keywords be atoms (although perhaps one could have a single
atom that indicates that all the succeeding lists are to be interpreted
as clauses rather than expressions).

Furthermore, what exactly *is* the status quo?  Is Symbolics going to
be nice and let us use their version of LOOP, which has some differences
from the standard?  What about the NAMED keyword?  I don't believe that's
available everywhere, but it seems like something better done with
CATCH and THROW anyway.  Is dependence on forms being processed "in order"
so deep that no one wants to make it optional (say for the compiler's
benefit)?  Perhaps somebody could give the official definition of the
"status quo" and then we could react to it...

							stan shebs
-------

∂10-Dec-84  1103	FAHLMAN@CMU-CS-C.ARPA 	Misc   
Received: from CMU-CS-C.ARPA by SU-AI.ARPA with TCP; 10 Dec 84  11:02:50 PST
Received: ID <FAHLMAN@CMU-CS-C.ARPA>; Mon 10 Dec 84 14:03:26-EST
Date: Mon, 10 Dec 1984  14:03 EST
Message-ID: <FAHLMAN.12070366478.BABYL@CMU-CS-C.ARPA>
Sender: FAHLMAN@CMU-CS-C.ARPA
From: "Scott E. Fahlman" <Fahlman@CMU-CS-C.ARPA>
To:   Stan Shebs <SHEBS@UTAH-20.ARPA>
Cc:   cl-iteration@SU-AI.ARPA
Subject: Misc
In-reply-to: Msg of 10 Dec 1984  13:11-EST from Stan Shebs <SHEBS at UTAH-20.ARPA>


Good network connections and some time to devote to this are more
important qualifications than "status", whatever that means.  The
chairpersons of these groups are not responsible for imposing solutions
on people, just for keeping the discussion lubricated and coherent.  So
if you want to volunteer and nobody else does, I think that gives you
sufficient status.

I think that what Guy meant by "the status quo" was that there is no
high-level looping construct in the white pages, just DO and friends,
along with the sequence functions.  I think most of us would like to see
a really good standard iteration facility, but DO is suficient until a
sufficiently good proposal comes along.

I think that if most of us can agree that some proposal is "the right
thing", any minor incompatibility with the current manual could be
fixed.  We want the language to be reasonably stable from now on, but
a minor change in the syntax of LOOP is not going to kill anyone.  In
any event, an easy fix is just not to call the new thing LOOP, but to
give it some other name.

I haven't studied the issue extensively, but my hunch is that I would
like something similar to the current Lisp Machine LOOP facility, but
with a more Lispy syntax -- parentheses replacing some of the
pseudo-english.  This PSL facility sounds like that.  Is a description
of it available online so that we could all take a look at it?

-- Scott

∂10-Dec-84  1644	SHEBS@UTAH-20.ARPA 	PSL's FOR Macro
Received: from UTAH-20.ARPA by SU-AI.ARPA with TCP; 10 Dec 84  16:43:48 PST
Date: Mon 10 Dec 84 17:44:55-MST
From: Stan Shebs <SHEBS@UTAH-20.ARPA>
Subject: PSL's FOR Macro
To: cl-iteration@SU-AI.ARPA

The PSL FOR macro description is not very long, so here it is:


(FOR . S:forms): any                                                      Macro

The arguments to FOR are clauses; each clause is itself a list of a keyword and
one or more arguments.  The clauses  may  introduce  local  variables,  specify
return  values  and  when the iteration should cease, have side-effects, and so
on.  Before going further, it is probably best to give some examples.

    (FOR (FROM I 1 10 2) (DO (PRINT I)))
            Prints the numbers 1 3 5 7 9

    (FOR (IN U '(A B C)) (DO (PRINT U)))
            Prints the letters A B C

    (FOR (ON U '(A B C)) (DO (PRINT U)))
            Prints the lists (A B C) (B C) and (C)

    Finally, the function
    (DE ZIP (X Y)
      (FOR (IN U X) (IN V Y)
            (COLLECT (LIST U V))))

produces a list of 2 element lists, each consisting of  the  the  corresponding
elements of the three lists X, Y and Z. For example, 

    (ZIP '(1 2 3 4) '(A B C) )

produces 

    ((1 a)(2 b)(3 c))

The iteration terminates as soon as one of the (IN ..) clauses is exhausted.

Note  that  the  (IN  ...  ),  (ON  ...) and (FROM ...) clauses introduce local
variables U, V or I, that are referred to in the action clause.

All the possible  clauses  are  described  below.    The  first  few  introduce
iteration  variables.    Most  of these also give some means of indicating when
iteration should cease.  For example, if a list being  mapped  over  by  an  IN
clause  is  exhausted, iteration must cease.  If several such clauses are given
in a FOR expression, iteration ceases when one  of  the  clauses  indicates  it
should, whether or not the other clauses indicate that it should cease.

(IN V1 V2)      assigns the variable V1 successive elements of the list V2.

                This  may  take an additional, optional argument: a function to
                be applied to the extracted element or  sublist  before  it  is
                assigned to the variable.  The following returns the sum of the
                lengths of all the elements of L. [Rather a kludge -- not  sure
                why this is here.  Perhaps it should come out again.]

                    (DE LENGTHS (L)
                      (FOR (IN N L LENGTH)
                    (COLLECT (LIST N N)))

                    is the same as

                    (DE LENGTHS (L)
                      (FOR (IN N L)
                         (COLLECT
                          (LIST (LENGTH N) (LENGTH N))))
                    )

                but  only  calls  LENGTH  once.  Using  the  (WITH  ..) form to
                introduce a local LN may be clearer.

                    For example,
                    (SUMLENGTHS
                     '((1 2 3 4 5)(a b c)(x y)))
                    is
                    ((5 5) (3 3) (2 2))

(ON V1 V2)      assigns the variable V1 successive CDRs of the list V2.

(FROM VAR INIT FINAL STEP)
                is  a numeric iteration clause.  The variable is first assigned
                INIT, and then incremented by step  until  it  is  larger  than
                FINAL.  INIT, FINAL, and STEP are optional.  INIT and STEP both
                default to 1, and if FINAL is omitted the  iteration  continues
                until stopped by some other means.  To specify a STEP with INIT
                or FINAL omitted, or a FINAL with INIT omitted, place NIL  (the
                constant -- it cannot be an expression) in the appropriate slot
                to be omitted.  FINAL and STEP are only evaluated once.

(FOR VAR INIT NEXT)
                assigns  the variable INIT first, and subsequently the value of
                the expression NEXT.  INIT and NEXT may be omitted.  Note  that
                this is identical to the behavior of iterators in a DO.

(WITH V1 V2 ... Vn)
                introduces N locals, initialized to NIL.  In addition, each  Vi
                may  also  be  of  the  form  (VAR  INIT),  in which case it is
                initialized to INIT.

(DO S1 S2 ... Sn)
                causes the Si's to be evaluated at each iteration.

There  are  two  clauses  which  allow arbitrary code to be executed before the
first iteration, and after the last.

(INITIALLY S1 S2 ... Sn)
                causes  the  Si's  to be evaluated in the new environment (i.e.
                with the iteration variables bound  to  their  initial  values)
                before the first iteration.

(FINALLY S1 S2 ... Sn)
                causes the Si's  to  be  evaluated  just  before  the  function
                returns.

The  next  few clauses build up return types.  Except for the RETURNS/RETURNING
clause, they may each take an additional argument which specifies that  instead
of  returning  the  appropriate  value,  it  is  accumulated  in  the specified
variable.  For example, an unzipper might be defined as 

    (DE UNZIP (L)
      (FOR (IN U L) (WITH X Y)
        (COLLECT (FIRST U) X)
        (COLLECT (SECOND U) Y)
        (RETURNS (LIST X Y))))

This is essentially the opposite of ZIP.  Given a list of 2 element  lists,  it
unzips  them  into  2 lists, and returns a list of those 2 lists.  For example,
(unzip '((1 a)(2 b)(3 c))) returns is ((1 2 3)(a b c)).

(RETURNS EXP)   causes the given  expression  to  be  the  value  of  the  FOR.
                Returning  is  synonymous  with  returns.    It  may  be  given
                additional arguments, in which case they are evaluated in order
                and the value of the last is returned (implicit PROGN).

(COLLECT EXP)   causes  the successive values of the expression to be collected
                into a list.  Each value is APPENDed to the end of the list.

(ADJOIN EXP), (ADJOINQ EXP)
                are similar to COLLECT, but a value is added to the result only
                if it is not already in the list.   ADJOIN  tests  with  EQUAL,
                ADJOINQ tests with EQ.

(CONC EXP)      causes the successive values to be NCONC'd together.

(JOIN EXP)      causes them to be appended.

(UNION EXP), (UNIONQ EXP)
                are similar to JOIN, but only add an element to the list if  it
                is  not  already  there.   UNION tests with EQUAL, UNIONQ tests
                with EQ.

(INTERSECTION EXP), (INTERSECTIONQ EXP)
                compute  the  set of elements that are in all the sets iterated
                over.  With INTERSECTION, elements are the same if EQUAL,  with
                INTERSECTIONQ they are the same if EQ.

(COUNT EXP)     returns the number of times EXP was non-NIL.

(SUM EXP), (PRODUCT EXP), (MAXIMIZE EXP), and (MINIMIZE EXP)
                do  the  obvious.    Synonyms  are  summing,  maximizing,   and
                minimizing.

(MAXIMAL EXP1 EXP2), (MINIMAL EXP1 EXP2)
                are  more  general  than  maximize  and  minimize.      MAXIMAL
                determines  the  greatest  value  for  EXP2 over the iteration,
                returning the value of EXP1 rather than the value of EXP2.   As
                a  particular  case  it  is  possible to return the value of an
                iteration variable for which some function  attains  a  maximum
                (or  minimum)  value,  e.g.  (MAXIMAL  x (f x)).  As with other
                kinds of clauses, the user may "accumulate" the value  of  EXP1
                into  a  variable  by supplying a third expression which is the
                name of a variable.

(ALWAYS EXP)    returns T if EXP is non-NIL on each iteration.  If EXP is  ever
                NIL, the loop terminates immediately, no epilogue code, such as
                that introduced by finally is run, and NIL is returned.

(NEVER EXP)     is equivalent to (ALWAYS (NOT EXP)).

(WHILE EXP) and (UNTIL EXP)
                Explicit  tests  for  the  end  of  the loop may be given using
                (WHILE EXP).  The loop terminates if EXP  becomes  NIL  at  the
                beginning  of  an  iteration.    (UNTIL EXP)  is  equivalent to
                (WHILE (NOT EXP)).    Both  WHILE  and  UNTIL  may   be   given
                additional  arguments;  (WHILE E1 E2 ... En)  is  equivalent to
                (WHILE (AND E1 E2 ... En))    and    (UNTIL E1 E2 ... En)    is
                equivalent to (UNTIL (OR E1 E2 ... En)).

(WHEN EXP)      causes a jump to the next iteration if EXP is NIL.

(UNLESS EXP)    is equivalent to (WHEN (NOT EXP)).

FOR  is  a general iteration construct similar in many ways to the Lisp Machine
and  MACLISP  LOOP  construct,  and  the  earlier  Interlisp  CLISP   iteration
construct.    FOR,  however,  is  considerably  simpler,  far more "lispy", and
somewhat less powerful.

All variable binding/updating still precedes any tests or  other  code.    Also
note  that  all  WHEN  or  UNLESS clauses apply to all action clauses, not just
subsequent ones.  This fixed order of evaluation makes FOR less  powerful  than
LOOP, but also keeps it considerably simpler.  The basic order of evaluation is

   1. bind variables to initial values (computed in the outer environment)

   2. execute prologue (i.e., INITIALLY clauses)

   3. while none of the termination conditions are satisfied:

         a. check  conditionalization clauses (WHEN and UNLESS), and start
            next iteration if all are not satisfied.

         b. perform body, collecting into variables as necessary

         c. next iteration

   4. (after a termination condition is satisfied)  execute  the  epilogue
      (i.e., FINALLY clauses)

FOR  does all variable binding/updating in parallel.  There is a similar macro,
FOR*, which does it sequentially.

(FOR* . S:forms): any                                                     Macro
-------

∂10-Dec-84  2006	JonL.pa@Xerox.ARPA 	Re: LOOP and Reply to Boyer   
Received: from XEROX.ARPA by SU-AI.ARPA with TCP; 10 Dec 84  20:06:12 PST
Received: from Semillon.ms by ArpaGateway.ms ; 10 DEC 84 20:06:52 PST
Date: 10 Dec 84 20:06 PST
From: JonL.pa@XEROX.ARPA
Subject: Re: LOOP and Reply to Boyer
In-reply-to: STEELE@TL-20A.ARPA's message of Mon, 10 Dec 84 11:05:59 EST
To: STEELE@TL-20A.ARPA
cc: cl-iteration@SU-AI.ARPA

Having used Interlisp's I.S.OPRS at length now, I want to re-confirm my
original support for the so-calld LOOP macro.  By the way, I thought one
of the versions did have a user-extensible syntax; has that been taken
out?

Regarding Bob's simplified example -- the fact that it could be written
with other CL constructs shouldn't be allow to occlude the very powerful
mechanism in user-extensibility, nor in the somewhat broader scope of
LOOP (as opposed to reduction operators).  

E.g.,  I once wrote an I.S.OPRS form called "inpname", which could be
very efficient on strings (works on all things -- just super-efficient
on strings):
   (for C inpname <mumble> do <look-for-something> 
      finally <break-if-get-here>)
A big "win" was to encapsulate in only one place the schema for how to
iterate over pnames -- I don't have to do it in a lot of little places
simply because there is some exception to the control structure of the
client code (in this case, the exception is what to do if you actually
reach the end!).  In the normal case, a function call on each character
would drastically impair performance.

Also the symmetric ability to mix iteration schema simplifies things;
consider the following Interlisp form:
   (during 300 timerUnits 'SECONDS 
    find MATRIX in L               ;"find" is like "for", but the 
    as I from 0 by 2               ; return value is implicitly MATRIX
    while (SunSetsInTheWest)
    suchthat (AREF MATRIX K I))
This loop has 4 different termination criteria, most of which would have
to be programmed separately in a functional-style program, and which
possibly would have to be programmed slightly differently depending on
context; but the I.S.OPRS mechanism, whether user-extensible  or not,
gives a feel not unlike a rule-based system -- you specify details and
order-of-execution only when it matters.  The macro (or DWIM in
Interlisp) figures out how to put the schema together.

-- JonL --




∂11-Dec-84  1903	FAHLMAN@CMU-CS-C.ARPA 	Lispy vs Pseudo-English Syntax  
Received: from CMU-CS-C.ARPA by SU-AI.ARPA with TCP; 11 Dec 84  19:02:43 PST
Received: ID <FAHLMAN@CMU-CS-C.ARPA>; Tue 11 Dec 84 22:03:15-EST
Date: Tue, 11 Dec 1984  22:03 EST
Message-ID: <FAHLMAN.12070715969.BABYL@CMU-CS-C.ARPA>
Sender: FAHLMAN@CMU-CS-C.ARPA
From: "Scott E. Fahlman" <Fahlman@CMU-CS-C.ARPA>
To:   cl-iteration@SU-AI.ARPA
Cc:   fahlman@CMU-CS-C.ARPA
Subject: Lispy vs Pseudo-English Syntax


I think the biggest problem we're going to have in coming up with a
standard iteration syntax is in finding some syntax that most of us can
live with.  Many of us deeply dislike the cutesy psuedo-English style of
the Zetalisp/Maclisp LOOP macro, yet the proponents of this style seem
to regard it as sacred.  I don't have my Chine Nual handy, but I recall
a sentence in there that says, more or less, the following: "Some may
feel that this English-like style is verbose and unsightly.  These
people are invited to use DO instead."  Well, I'm one of those people,
and I've been using DO instead.  I don't even like to read that other
stuff, let alone try to write it.  Still, I can see the desirability of
having facilities like COLLECT and MAXIMIZE built into Common Lisp, so
that people don't have do such things in ad hoc ways inside of DO loops.

The kind of syntax in the PSL FOR macro (as described in the recent note
by Shebs) looks much better to me: a free mixture of clauses, each
introduced by a keyword and each one in a sublist of its own.  I think
that this question of syntax is orthogonal to the other differences
between FOR and LOOP; whatever we decide to do about such issues as
order-of-evaluation constraints, user extensibility, which forms to
include, and so on, it should be possible to implement these decisions
in either syntax.

The lispy syntax of FOR seems better to me for a number of reasons:

1. I don't like pseudo-English in those business-oriented langauges that
try to dupe businessmen into believing that they can program their
IBM-PC in raw English, and I like pseudo-English even less in Lisp
(whose power would make such claims more plausible but no more true).
We are dealing here with a very restricted, very precise formal language
with a simple, dumb parser.  It is a cruel hoax to pretend that this is
English and that the resulting code means just what the corresponding
English sentence would mean.  You must carefully understand and memorize
what each of the keywords means in each context -- you cannot just write
a sentence and expect the Lisp system to do the right thing.  I find
such pseudo-English to be more confusing than an obviously artificial
language, not less.

2. I believe that the parenthesized form is easier to read quickly, at
least for people used to Lisp syntax.  The grouping of operators and
their arguments is visually evident; it is much harder for me to
immediately grasp what some run-on pseudo-sentence, with chunks of
undigested Lisp code floating around in it, is going to do.

3. The unusual syntax of LOOP makes life difficult for various
components of the programming environment.  The difficulty of parsing
the pseudo-English in the LOOP macro itself is not really an issue,
since that code only needs to be written once and prototypes already
exist, but a lot of other tools such as pretty printers would have to be
modified to understand which keywords want to cause line breaks, etc.

4. Where a clause takes more than one argument-like form, the lispy
syntax is more flexible.  An explictly delimited clause can take any
number of by-position arguments, while the LOOP syntax requires that
each of the additional arguments either be recognizable as a non-keyword
or that it be introduced by some marker, usually an English preposition
like "by" or "to".  I find it very difficult to remember which of these
little syntactic markers go with which clauses and perform which
operations.

5. The conceit that a LOOP expression should read like a grammatical
English sentence (though one that is unlikely to come up in polite
converstion) leads to some poor choices of keywords.  In order to get
the pseudo-sentences to sound right when pronounced, you need to define
lots of synonyms, so that both the singular and plural forms, or both
plain and "ing" forms, are allowed.  Keywords are chosen so that the
sentences sound natural, rather than on the basis of how clearly they
will convey the precise meaning of the operation.

As far as number of keystrokes are concerned, I think it's about even.
The parentheses add up, but often a couple of parentheses can eliminate
two or three little connecting words.  It seems to me that the principal
advantages of the LOOP syntax are that some people are used to it
already and that some small number of people think that it is cute.

Comments?

Two additional thoughts:

The labelled clauses in the FOR syntax look too much like Lisp
expressions, since some of the labels are identical to built-in Lisp
functions and special forms.  I can imagine some Emacs character macro
being screwed by trying to find all the (unless ...) expressions and not
realizing that the ones inside a FOR construct are different from the
ones outside.  Maybe these labels should be keywords, as in (:unless
expression) ?  One more character to type, but it would make it very
easy to distinguish the clauses of an iteration from random functions
and special forms.

I suppose that one possibility would be sanction both the Lisp-like and
pseudo-English types of syntax, with a simple one-to-one correspondence.
Then people could write in whichever surface style they choose, and they
could even convert programs written by others into their own preferred
syntax before trying to understand them.  I don't much like this kind of
solution, but if there is an irreconcilable division over this issue of
syntax, this might be better than no solution at all.

-- Scott

∂11-Dec-84  2050	JonL.pa@Xerox.ARPA 	Re: Lispy vs Pseudo-English Syntax 
Received: from XEROX.ARPA by SU-AI.ARPA with TCP; 11 Dec 84  20:49:51 PST
Received: from Burger.ms by ArpaGateway.ms ; 11 DEC 84 20:51:24 PST
Date: 11 Dec 84 20:49 PST
From: JonL.pa@XEROX.ARPA
Subject: Re: Lispy vs Pseudo-English Syntax
In-reply-to: "Scott E. Fahlman" <Fahlman@CMU-CS-C.ARPA>'s message of
 Tue, 11 Dec 84 22:03 EST
To: Fahlman@CMU-CS-C.ARPA
cc: cl-iteration@SU-AI.ARPA

I'd say that a strong argument for LOOP, in addition to its use by some
current MacLisp/LispM people, is that it reflects quite well the
capabilities and syntax of Interlisp's I.S.OPRS; and those potential
CommonLisp users with some Interlisp experience will find it quite
comfortable.  Not to be overlooked is the fact that I.S.OPRS has had
over a decade of life in the Interlisp community, and is "dearly loved"
there; many other CLISPisms have not passed the test of time so well.

This brings up another point -- your suggestion to support both
syntaxes.  I don't think there is any technical conflict to doing so.
In fact, I'd rather see such a mandate broadened to treat IF in the same
way that Franz did; namely:
    (if (test) A B)
is expressed in Interlisp form as
    (if (test) 
        then A
      else B)
What the Franz folks noticed is that the only conflict between the two
is when one wants to return a variable whose name is "then" or "else".
So their IF macro accepts both forms, presumably just "biting the
bullet" on "then" and "else".  I personally find "elseif" useful too:
   (cond (p1 ...e1) (p2 ...e2) . . . (pn ...en))
becomes
   (if p1
       then ...e1
     elseif p2
       then ...e2
    . . . 
     elseif pn
       then ...en)

As to one's personal stylistic preference for syntax -- well, one man's
meat is another's poison.  But in defense of the expanded "if" over
"cond", more 2-dimensional prettyprinting as opposed to "dense" code,
and keyword-driven parsing ocasionally dispensing with parentheses, one
can point to many vanilla computer languages that take on these more
"familiar" names and styles *without making any pretensions to being
'english-like'*.  (C comes to mind, even though is is probably the worst
of all such examples!).

-- JonL --


 


∂12-Dec-84  0719	FAHLMAN@CMU-CS-C.ARPA 	Lispy vs Pseudo-English Syntax  
Received: from CMU-CS-C.ARPA by SU-AI.ARPA with TCP; 12 Dec 84  07:19:05 PST
Received: ID <FAHLMAN@CMU-CS-C.ARPA>; Wed 12 Dec 84 10:19:43-EST
Date: Wed, 12 Dec 1984  10:19 EST
Message-ID: <FAHLMAN.12070850046.BABYL@CMU-CS-C.ARPA>
Sender: FAHLMAN@CMU-CS-C.ARPA
From: "Scott E. Fahlman" <Fahlman@CMU-CS-C.ARPA>
To:   JonL.pa@XEROX.ARPA
Cc:   cl-iteration@SU-AI.ARPA
Subject: Lispy vs Pseudo-English Syntax
In-reply-to: Msg of 11 Dec 1984  23:49-EST from JonL.pa at XEROX.ARPA


Well, if the overwhelming majority of people who have used LOOP or
I.S.OPRS for a year or two think that it's a truly winning syntax, I'd
have to take that as evidence that I'm wrong about all this.  That is
especially true if people like the iteration syntax in CLISP, but don't
like the rest of CLISP; anyone who likes ALL of CLISP should be
programming in Algol rather than Lisp and doesn't belong in this
sample.

As for the IF/ELSEIF business, that can be handled easily by a macro for
those who like this sort of thing, and I don't think that having
aternative forms in the standard language is very useful.  I once saw,
in some code by Joe Ginder, a very simple extension for IF that gives
you some of the same effect: just define (THEN forms) and (ELSE forms)
as macros that turn into (PROGN forms).  So you end up with something
that looks like the following:

(if (foop)
    (then (clause1)
          (clause2)
          (clause3))
    (else (mumble1)
          (mumble2)))

I almost proposed this for incorporation into standard Common Lisp, but
that was back when we thought the language was going to be small and
elegant, so I didn't bring it up.

-- Scott

∂13-Dec-84  2021	CL.BOYER@UTEXAS-20.ARPA 	[CL.BOYER@UTEXAS-20: defmacro]
Received: from UTEXAS-20.ARPA by SU-AI.ARPA with TCP; 13 Dec 84  20:20:52 PST
Date: Thu, 13 Dec 1984  22:16 CST
From: CL.BOYER@UTEXAS-20.ARPA
To:   "David A. Moon" <Moon@SCRC-QUABBIN>
Cc:   cl-iteration@SU-AI, STEELE@TL-20A
Subject: [CL.BOYER@UTEXAS-20: defmacro]
In-reply-to: Msg of 13 Dec 1984  15:43-CST from "David A. Moon" <Moon at SCRC-QUABBIN.ARPA>

I should have said &rest instead of &whole.  Sorry for the
slip.

∂20-Dec-84  1451	Moon%SCRC-STONY-BROOK.ARPA@MIT-XX.ARPA 	[CL.BOYER@UTEXAS-20.ARPA: defmacro]
Received: from MIT-XX.ARPA by SU-AI.ARPA with TCP; 20 Dec 84  14:51:00 PST
Received: from SCRC-STONY-BROOK by MIT-XX via Chaosnet; 20-Dec-84 17:52:24-EST
Received: from SCRC-EUPHRATES by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 147354; Thu 20-Dec-84 17:33:22-EST
Date: Thu, 20 Dec 84 17:31 EST
From: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Subject: [CL.BOYER@UTEXAS-20.ARPA: defmacro]
To: cl-iteration%SU-AI@MIT-XX.ARPA
In-Reply-To: The message of 10 Dec 84 10:54-EST from STEELE@TL-20A.ARPA
Message-ID: <841220173112.3.MOON@EUPHRATES.SCRC.Symbolics.COM>

I don't know why cl-iteration is the right group on which to discuss this,
but let that pass.

    Date: Mon 10 Dec 84 10:54:51-EST
    From: STEELE@TL-20A.ARPA

    Date: Sun, 9 Dec 1984  16:38 CST
    From: CL.BOYER@UTEXAS-20.ARPA

    Finally, and totally unrelatedly, is it true that

	 (defmacro foo x ...)

    is not permited in Common Lisp and that
    I need to write

	 (defmacro foo (&whole x) ...)?

    I'm trying to find some common ground with psl and the maclisp
    dialects, but it doesn't look like there is a general
    purpose intersection.  As I read it, a lambda list has
    to be a list, and that excludes a symbolp.

    P.S. Hedrick's 2060 Common Lisp permits (defmacro foo x ...).

Our defmacro treats (defmacro foo x ...) as equivalent to
(defmacro foo (&rest x) ...) rather than (defmacro foo (&whole x) ...).
Which interpretation does Hedrick's use?

I guess this ambiguity makes it quite clear why Common Lisp doesn't allow it.

∂20-Dec-84  1731	Moon%SCRC-STONY-BROOK.ARPA@MIT-XX.ARPA 	[CL.BOYER@UTEXAS-20.ARPA: defmacro]
Received: from MIT-XX.ARPA by SU-AI.ARPA with TCP; 20 Dec 84  17:31:17 PST
Received: from SCRC-STONY-BROOK by MIT-XX via Chaosnet; 20-Dec-84 20:33:01-EST
Received: from SCRC-EUPHRATES by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 147498; Thu 20-Dec-84 20:32:41-EST
Date: Thu, 20 Dec 84 20:30 EST
From: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Subject: [CL.BOYER@UTEXAS-20.ARPA: defmacro]
To: cl-iteration%SU-AI@MIT-XX.ARPA
In-Reply-To: <841220173112.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <841220203024.4.MOON@EUPHRATES.SCRC.Symbolics.COM>

    Date: Thu, 20 Dec 84 17:31 EST
    From: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>

    I don't know why cl-iteration is the right group on which to discuss this,
    but let that pass.

	Date: Mon 10 Dec 84 10:54:51-EST
	From: STEELE@TL-20A.ARPA

	Date: Sun, 9 Dec 1984  16:38 CST
	From: CL.BOYER@UTEXAS-20.ARPA

	Finally, and totally unrelatedly, is it true that

	     (defmacro foo x ...)

	is not permited in Common Lisp and that
	I need to write

	     (defmacro foo (&whole x) ...)?

	I'm trying to find some common ground with psl and the maclisp
	dialects, but it doesn't look like there is a general
	purpose intersection.  As I read it, a lambda list has
	to be a list, and that excludes a symbolp.

	P.S. Hedrick's 2060 Common Lisp permits (defmacro foo x ...).

    Our defmacro treats (defmacro foo x ...) as equivalent to
    (defmacro foo (&rest x) ...) rather than (defmacro foo (&whole x) ...).
    Which interpretation does Hedrick's use?

    I guess this ambiguity makes it quite clear why Common Lisp doesn't allow it.

Since Boyer later explained that his &WHOLE was a typo for &REST, it seems that
there is only one proposed meaning for (defmacro foo x ...).  Furthermore, the
generalization from (defmacro foo ((&rest x)) ...) = (defmacro foo (x) ...)
to (defmacro foo (&rest x) ...) = (defmacro foo x ...) seems like a natural one
for users to assume.

Should this be moved off of cl-iteration and proposed to common-lisp at large?
I don't care much, personally.

∂21-Dec-84  1756	Moon%SCRC-STONY-BROOK.ARPA@MIT-XX.ARPA 	Unable to deliver letter 
Received: from MIT-XX.ARPA by SU-AI.ARPA with TCP; 21 Dec 84  17:56:25 PST
Received: from SCRC-STONY-BROOK by MIT-XX via Chaosnet; 21-Dec-84 20:58:03-EST
Received: from SCRC-EUPHRATES by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 147992; Fri 21-Dec-84 16:52:17-EST
Return-path: <Postmaster@SCRC-STONY-BROOK>
Received: from SCRC-STONY-BROOK by SCRC-TENEX with CHAOS; Fri 21-Dec-84 16:49:30-EST
Date: Friday, 21 December 1984, 16:47-EST
From: Postmaster at SCRC-STONY-BROOK
Subject: Unable to deliver letter
To: Moon at SCRC-STONY-BROOK
Resent-To: cl-iteration%su-ai@MIT-XX.ARPA
Resent-From: Moon@SCRC-STONY-BROOK.ARPA
Resent-Date: Fri, 21 Dec 84 16:49 EST
Resent-Message-ID: <841221164942.0.MOON@EUPHRATES.SCRC.Symbolics.COM>

Unable to deliver letter to the following recipient:
  cl-iteration at SU-AI: Host not responding.

----- Text of letter follows -----
Received: from SCRC-EUPHRATES by SCRC-STONY-BROOK via CHAOS with CHAOS-MAIL id 145892; Tue 18-Dec-84 16:02:59-EST
Date: Tue, 18 Dec 84 16:02 EST
From: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Subject: PSL's FOR Macro
To: Stan Shebs <SHEBS@UTAH-20.ARPA>
cc: cl-iteration@SU-AI.ARPA
In-Reply-To: The message of 10 Dec 84 19:44-EST from Stan Shebs <SHEBS@UTAH-20.ARPA>
Message-ID: <841218160257.9.MOON@EUPHRATES.SCRC.Symbolics.COM>

I think it would be great if a Common Lisp version of PSL's FOR macro were
written and submitted to the Yellow Pages.  I also think it would be great
if there were a Yellow Pages at all!

I personally would never use this macro if I had an alternative, primarily
because of the fixed order of evaluation, which means that you can write code
that looks like it will be evaluated in a certain order, but actually it
will be evaluated in a different order, causing subtle bugs.  I also find the
syntax less readable than the syntax of LOOP, but that of course is more a
matter of personal taste than of anything that a group could agree on.

∂02-Jan-85  1711	@MIT-MC:MOON@SCRC-TENEX 	PSL's FOR Macro
Received: from MIT-MC.ARPA by SU-AI.ARPA with TCP; 2 Jan 85  17:11:41 PST
Date: Wednesday, 2 January 1985  20:13-EST
From: MOON at SCRC-TENEX
To:   cl-iteration%su-ai at mit-mc
Subject: PSL's FOR Macro

I've been trying for two weeks now to get this message through.
This is the fifth attempt; maybe this route to SU-AI will work.

Date: Tue, 18 Dec 84 16:02 EST
From: Moon@SCRC-STONY-BROOK.ARPA
Subject: PSL's FOR Macro
To: SHEBS@UTAH-20.ARPA
cc: cl-iteration@SU-AI.ARPA
In-Reply-To: The message of 10 Dec 84 19:44-EST from SHEBS at UTAH-20
Message-ID: <841218160257.9.MOON@EUPHRATES.SCRC.Symbolics.COM>

I think it would be great if a Common Lisp version of PSL's FOR macro were
written and submitted to the Yellow Pages.  I also think it would be great
if there were a Yellow Pages at all!

I personally would never use this macro if I had an alternative, primarily
because of the fixed order of evaluation, which means that you can write code
that looks like it will be evaluated in a certain order, but actually it
will be evaluated in a different order, causing subtle bugs.  I also find the
syntax less readable than the syntax of LOOP, but that of course is more a
matter of personal taste than of anything that a group could agree on.