From: William Paul Vrotney
Subject: docdrs
Date: 
Message-ID: <vrotneyEnBwrA.qx@netcom.com>
Why was a macro like DOCDRS defined by

    ; Similar to DOLIST but operates on the cdrs of the given list.
    (defmacro docdrs ((x list result) . body)
      `(do ((,x ,list (cdr ,x))) ((not ,x) ,result) ,.body))

not specified for Common Lisp?  Feels like a piece of symmetry is missing
without it.

The argument that there is a MAPL is not good enough since the same could be
argued for MAPC/DOLIST.  Also, arguments related to extended LOOP are not
relevant.



-- 

William P. Vrotney - ·······@netcom.com

From: Kent M Pitman
Subject: Re: docdrs
Date: 
Message-ID: <sfwpvlgjwpz.fsf@world.std.com>
·······@netcom.com (William Paul Vrotney) writes:

> Why was a macro like DOCDRS defined by
> 
>     ; Similar to DOLIST but operates on the cdrs of the given list.
>     (defmacro docdrs ((x list result) . body)
>       `(do ((,x ,list (cdr ,x))) ((not ,x) ,result) ,.body))
> 
> not specified for Common Lisp?  Feels like a piece of symmetry is missing
> without it.

[Hmm.  Looks to me like it'd be pronounced "doc-doctors"
("dr" = "doctor", "drs" presumably being its plural).  ]

Common Lisp was not the design of a language as much as the codification
of the unified design of several dialects.  DOCDRS was not in any language
and you are the first person I've heard propose it in my 21 years  of work 
with Lisp, so as a not-very-scientific statistic, I'd say CL did the right
thing in not bothering with that specific syntax. 

It's not that no one has wanted the functionality generally, it's just
that loops are arbitrarily complicated and that's why CL folks have over
time leaned heavily on LOOP.  Even I, an die-hard anti-LOOP fanatic, have
softened to it over the years because of its flexibility.
  
 (loop for x on y do ...) does what you want.

I most frequently use this for walking down property lists, which your
proposed operator cannot do.

 (loop for (key val) on plist by #'cddr do ....)

I think CL made the right decision in providing a flexible, reasonably
general purpose syntax.  There are many specific grumblings I have with 
the specifics of the syntax, but fundamentally I think looping is a hard
problem and that CL goes a long way to make it easier.

> The argument that there is a MAPL is not good enough since the same could be
> argued for MAPC/DOLIST.

I would never use MAPL.  It and its friends are there for historical
reasons and I find most of them painful.  Also, in many implementations
the compiler doesn't know when to open-code the loop and when not.

> Also, arguments related to extended LOOP are not
> relevant.

Oops.  I didn't notice this remark until last.  Well, anyway, this
claim will require more support.  I'm not going to let you get away
that easily.  My inclinations may be similar, but I've forced myself
to look better at LOOP--and I think it's often given too little attention.
From: William Paul Vrotney
Subject: Re: docdrs
Date: 
Message-ID: <vrotneyEnE0tK.15p@netcom.com>
In article <···············@world.std.com> Kent M Pitman
<······@world.std.com> writes:

> 
> ·······@netcom.com (William Paul Vrotney) writes:
> 
> > Why was a macro like DOCDRS defined by
> > 
> >     ; Similar to DOLIST but operates on the cdrs of the given list.
> >     (defmacro docdrs ((x list result) . body)
> >       `(do ((,x ,list (cdr ,x))) ((not ,x) ,result) ,.body))
> > 
> > not specified for Common Lisp?  Feels like a piece of symmetry is missing
> > without it.
> 
> [Hmm.  Looks to me like it'd be pronounced "doc-doctors"
> ("dr" = "doctor", "drs" presumably being its plural).  ]
> 

I agree the name DOCDRS is an ugly name.  Suggestions for a better name are
welcomed.  Perhaps DO-CDRS is better.  Of course the *name* DOCDRS is not
the point here.

> Common Lisp was not the design of a language as much as the codification
> of the unified design of several dialects.  DOCDRS was not in any language
> and you are the first person I've heard propose it in my 21 years  of work 
> with Lisp, so as a not-very-scientific statistic, I'd say CL did the right
> thing in not bothering with that specific syntax. 
> 

Well, although I am surprised that you have never heard anyone else suggest
the idea (not the name per se), this is good input and perhaps answers my
question.  As long as I have the macro ability to define something like
DOCDRS I have no gripe, just a curiosity.


> It's not that no one has wanted the functionality generally, it's just
> that loops are arbitrarily complicated and that's why CL folks have over
> time leaned heavily on LOOP.  Even I, an die-hard anti-LOOP fanatic, have
> softened to it over the years because of its flexibility.
>   
>  (loop for x on y do ...) does what you want.
> 

That is not the point either; so does DO.

> I most frequently use this for walking down property lists, which your
> proposed operator cannot do.
> 
>  (loop for (key val) on plist by #'cddr do ....)
> 

That is not the point either; there are a lot of things that DOLIST can not
do but Lisp programmers use it.


> I think CL made the right decision in providing a flexible, reasonably
> general purpose syntax.  There are many specific grumblings I have with 
> the specifics of the syntax, but fundamentally I think looping is a hard
> problem and that CL goes a long way to make it easier.
> 

Agreed.

> > The argument that there is a MAPL is not good enough since the same could be
> > argued for MAPC/DOLIST.
> 
> I would never use MAPL.  It and its friends are there for historical
> reasons and I find most of them painful.  Also, in many implementations
> the compiler doesn't know when to open-code the loop and when not.

As a mind experiment, if given the chance to do so now would you feel secure
enough to exclude MAPL and those friends from the spec?  If so, would you
keep any list mapping functions?  Just curious.

> 
> > Also, arguments related to extended LOOP are not
> > relevant.
> 
> Oops.  I didn't notice this remark until last.  Well, anyway, this
> claim will require more support.  I'm not going to let you get away
> that easily.  My inclinations may be similar, but I've forced myself
> to look better at LOOP--and I think it's often given too little attention.
> 

The statement "arguments related to extended LOOP are not relevant" was
meant as defining and limiting the scope of the symmetry question for
DOLIST/DOCDRS and not a claim denigrating extended-LOOP.  It therefore
hopefully does not need support from this perspective.

Believe me, for more years than I care to admit I've looked at extended-LOOP
from both sides.  I even helped debug the original extended-LOOP code for at
least one platform.  Granted, extended-LOOP is powerful but specific
iteration schemas have redeeming qualities that extended-LOOP lacks.  For
example in your plist example

        (loop for (key val) on plist by #'cddr do ....)

one could counter that if one had to do this a lot, then with a specific
macro like

        (do-plist (var val) ...)

it is clearer, shorter to type, more Lispy, one does not have to learn the
extended-LOOP language to read this code and one would not have to load the
huge extended-LOOP code to read this code.  These are all redeeming
qualities *despite* the fact that one would have to define this macro
specifically, learn it specifically and that it would not have the "loopy
extensibility" of extended-LOOP.  Perhaps this is why specific iteration
schemas endure.  

I agree that Lisp programmers should consider the extended-LOOP language.
But it is a good thing Lisp programmers have the choice to *not* use
extended-LOOP if they so choose.  Do you agree?





-- 

William P. Vrotney - ·······@netcom.com
From: Kelly Murray
Subject: Re: docdrs
Date: 
Message-ID: <6aj56r$p1k$1@news2.franz.com>
> I agree that Lisp programmers should consider the extended-LOOP language.
> But it is a good thing Lisp programmers have the choice to *not* use
> extended-LOOP if they so choose.  Do you agree?

LOOP is a macro, and therefore could be eliminated from a runtime system.
The MAPxxx (and sequence functions as well) are functions, and
thus must be included in a runtime system in case someone calls them.

So it is "free" (at runtime) for the non-loop user to allow a LOOP choice,
but the LOOP-only user must "pay" for the non-loop choice.  Is that "fair"?

The MAP and sequence functions and other iterative macros
can be defined fairly easily using LOOP.

The cost of supported non-loop code with any efficiency requires a vast
amount of compile-time AND a lot of runtime optimizers.
LOOP requires only a lot of compiler optimizers.

The documentation burden for all the sequence and map functions
is also quite large, and for the novice the huge manual is intimidating,
and doesn't give students confidence they understand how to use the
language until the know about all those functions.
In addition, one can't understand other peoples code that uses them,
so even beyond-beginners have limited ability to use and reuse others code.

Therefore, my opinion is that a new language standard that 
could free itself from the heavy burden of backward  compatibility 
and historical baggage, would define ONLY LOOP in the language.



-Kelly Murray  ···@franz.com   
From: William Paul Vrotney
Subject: Re: docdrs
Date: 
Message-ID: <vrotneyEnF9ML.M2n@netcom.com>
In article <············@news2.franz.com> ···@math.ufl.edu (Kelly Murray)
writes:

> 
> > I agree that Lisp programmers should consider the extended-LOOP language.
> > But it is a good thing Lisp programmers have the choice to *not* use
> > extended-LOOP if they so choose.  Do you agree?
> 
> LOOP is a macro, and therefore could be eliminated from a runtime system.
> The MAPxxx (and sequence functions as well) are functions, and
> thus must be included in a runtime system in case someone calls them.
> 

There are two things incorrect about this.

First, a macro is defined by a macro generating function that is not by
default eliminated from the run time system.  So LOOP is the same as MAPxxx
in this respect.  Here is an example

        (defun Im-around-at-runtime ()
          (macroexpand '(loop for i from 1 to 5 do (print i))))

Second, *both* the LOOP expansion function and the MAPxxx functions in
principle can be eliminated from the run time system by a tree shaker and
then a save image.


> So it is "free" (at runtime) for the non-loop user to allow a LOOP choice,
> but the LOOP-only user must "pay" for the non-loop choice.  Is that "fair"?
> 
> The MAP and sequence functions and other iterative macros
> can be defined fairly easily using LOOP.
> 

Unless an implementation has iterative macros that are also special forms
all looping macro code regardless of where it is defined is macro expanded
into TAGBODYs with GOs.  So MAP (if written using looping macros), DO,
DOLIST, LOOP etc. are all on the same level in this regard.

> The cost of supported non-loop code with any efficiency requires a vast
> amount of compile-time AND a lot of runtime optimizers.
> LOOP requires only a lot of compiler optimizers.
> 
> The documentation burden for all the sequence and map functions
> is also quite large, and for the novice the huge manual is intimidating,
> and doesn't give students confidence they understand how to use the
> language until the know about all those functions.

Well, in CLTL2 extended-LOOP is 34 pages and the Iteration section
including the Mapping functions is only 10 pages.

The sequence functions are in a different non-one-to-one category, for
example concatenation is not a looping operation.

> In addition, one can't understand other peoples code that uses them,
> so even beyond-beginners have limited ability to use and reuse others code.
> 

This actually is one of the anti-extended-LOOP advocates biggest arguments
against extended-LOOP: Heavy use of combined extended-LOOP clauses is very
non-Lispy and loses it clean Lispy block structure and is hard to follow and
debug.

I can vouch for this.  I can't tell you the number of times I've had to
rewrite large amorphous chunks of extended-LOOP code into Lisp (note the
dig) so that I could understand what was going on.  And this is not because
I am more familiar in one than the other.

> Therefore, my opinion is that a new language standard that 
> could free itself from the heavy burden of backward  compatibility 
> and historical baggage, would define ONLY LOOP in the language.
> 

Ah, my suspicion that extended-LOOP radicals exist is true. :-)
-- 

William P. Vrotney - ·······@netcom.com
From: Kelly Murray
Subject: Re: docdrs
Date: 
Message-ID: <6ak466$bbt$1@news2.franz.com>
> First, a macro is defined by a macro generating function that is not by
> default eliminated from the run time system.  So LOOP is the same as MAPxxx
>in this respect.  Here is an example
>        (defun Im-around-at-runtime ()
>          (macroexpand '(loop for i from 1 to 5 do (print i))))
>Second, *both* the LOOP expansion function and the MAPxxx functions in
>principle can be eliminated from the run time system by a tree shaker and
>then a save image.

In principle. In practice, tree shakers don't exist and don't work.
It is easy and practical to remove the compiler and EVAL for a runtime system,
in which case all macros can be safely removed.  Not true for MAPxxx functions.

Does a stripped runtime matter?  If you have to download it into a web browser,
then, yes, size matters very much.  If it sits on the server, then it makes
no practical difference whether the entire development environment is still
around.

> Well, in CLTL2 extended-LOOP is 34 pages and the Iteration section
> including the Mapping functions is only 10 pages.

The MAPxxx functions essentially require understanding functional arguments,
in particular closures #'(lambda ..).  So the documentation and learnability
burden is really quite larger than a page count indicates.

In any case, the full LOOP capability is way too much.
Conditionals, summing, appending, etc,
packages, hashtables, are all uneeded.  
I advocate only its simpler constructs.  Certainly documenting only
the capabilities related to support for MAPxxx functions would be
very little, yet it would be capable of a LOT more.

>> In addition, one can't understand other peoples code that uses them [sequence and
>> maps] so even beyond-beginners have limited ability to use and reuse others code.
>> 
>This actually is one of the anti-extended-LOOP advocates biggest arguments
>against extended-LOOP: Heavy use of combined extended-LOOP clauses is very
>non-Lispy and loses it clean Lispy block structure and is hard to follow and
>debug.

I agree.  I'm one in the anti-extended-out-the-whaazoo-LOOP camp.
I advocate a simple LOOP.  The full LOOP syntax is too much of a good thing.

>> Therefore, my opinion is that a new language standard that 
>> could free itself from the heavy burden of backward  compatibility 
>> and historical baggage, would define ONLY LOOP in the language.
>
>Ah, my suspicion that extended-LOOP radicals exist is true. :-)

I suppose if not using a MAPxxx function, DOLIST or DOTIMES or DO
for years now and still producing a ton of working and maintained code
is a radical idea, then I plead guilty.

-Kelly Murray  ···@franz.com
From: Jeffrey Mark Siskind
Subject: Re: docdrs
Date: 
Message-ID: <yq7wwflfd15.fsf@qobi.nj.nec.com>
> In principle. In practice, tree shakers don't exist and don't work.
> It is easy and practical to remove the compiler and EVAL for a runtime
  system,
> in which case all macros can be safely removed.  Not true for MAPxxx
  functions.

Take a look at Stalin. Stalin does exist and does work. And it does generate
the same code for calls to (higher-order procedures like) MAP as for (macros
like) DO. And in neither case are there unused procedures at run time. Not by
special case hacks (like tree shaking) as is done by every Common Lisp compiler
in existence but rather by extremely powerful and general program analysis and
transformation techniques. So your choice between MAP and DO is based on
stylistic preferences and the relative power of the programming language
constructs involved, not on their relative performance.

Now it is true that Stalin is not yet anywhere near the level of robustness
and practicality for large programs as mainstream Common Lisp systems. But
that is a question of engineering, not of fundamental feasibility.

    Jeff (http://www.neci.nj.nec.com/homepages/qobi)
From: Hrvoje Niksic
Subject: Re: docdrs
Date: 
Message-ID: <kigyb03la76.fsf@jagor.srce.hr>
·······@netcom.com (William Paul Vrotney) writes:

>         (loop for (key val) on plist by #'cddr do ....)
> 
> one could counter that if one had to do this a lot, then with a specific
> macro like
> 
>         (do-plist (var val) ...)
> 
> it is clearer, shorter to type, more Lispy, one does not have to
> learn the extended-LOOP language to read this code and one would not
> have to load the huge extended-LOOP code to read this code.

A-men.  One problem I have with the LOOP macro is that I find it
toally unreadable and unlispy.  Maybe I've been spoiled by all the
parentheses in "other" parts of Lisp, but their lack in LOOP is
totally disconcerting, especially with more complex expressions.

At first I've written it off as a frivolity of my own, but in the
meantime I've seen the same view shared by a disconcerting number of
people.

-- 
Hrvoje Niksic <·······@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------
The end of the world is coming...  SAVE YOUR BUFFERS!
From: Pierpaolo Bernardi
Subject: Re: docdrs
Date: 
Message-ID: <6aibo5$18vi$1@serra.unipi.it>
Kent M Pitman (······@world.std.com) wrote:
: ·······@netcom.com (William Paul Vrotney) writes:

  ...

: I would never use MAPL.  It and its friends are there for historical
: reasons and I find most of them painful.  Also, in many implementations
: the compiler doesn't know when to open-code the loop and when not.

FWIW, I often use mapl in situations like the following:

(mapl (lambda (x)
        (princ (first x))
        (when (rest x)
          (princ ", ")))
      list-of-foos)

Both loop and format could be used in this case, but I prefer to write
Lisp, instead.


Pierpaolo
From: Barry Margolin
Subject: Re: docdrs
Date: 
Message-ID: <8u5z.31$pX3.1389694@cam-news-reader1.bbnplanet.com>
To answer the original poster's question, I believe the mapping functions
were defined relatively early in Lisp's life (probably in the 60's).  They
defined a pretty complete set, providing versions that apply to elements
and cdrs, and that combine the results using LIST and NCONC.  At that time,
it wasn't yet obvious which would be popular; they just created a bunch of
looping primitives that seemed useful.  This was probably before DO
existed, so the only other way to do iteration was PROG and GO, which is
also considered un-LISPy.

Later on, as Lisp cliches developed, iterating over elements of lists was
found to be extremely common.  Many people had macros similar to DOLIST
in their personal repertoires, and it was eventually put into the standard
macro package used in Maclisp, Zetalisp and other contemporaries.  From
there, it was incorporated into Common Lisp.

Iterating over successive tails was not as common, so such macros weren't
necessary, and hence they didn't end up in CL.

In article <·············@serra.unipi.it>,
Pierpaolo Bernardi <········@cli.di.unipi.it> wrote:
>FWIW, I often use mapl in situations like the following:
>
>(mapl (lambda (x)
>        (princ (first x))
>        (when (rest x)
>          (princ ", ")))
>      list-of-foos)

FWIW, I usually implement that like:

(when list-of-foos
  (princ (car list-of-foos))
  (dolist (foo (cdr list-of-foos))
    (format t ", ~A" foo)))

or

(let ((first-time t))
  (dolist (foo list-of-foos)
    (if first-time
        (setq first-time nil)
	(princ ", "))
    (princ foo)))



-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
Support the anti-spam movement; see <http://www.cauce.org/>
Please don't send technical questions directly to me, post them to newsgroups.
From: Tim Bradshaw
Subject: Re: Simplified LOOP
Date: 
Message-ID: <ey3d8gxqett.fsf@todday.aiai.ed.ac.uk>
* Sunil Mishra wrote:

> At the end of cltl2 there is a section about a proposed series mechanism,
> which can potentially allow us to get around many issues. I, certainly,
> have no idea what the implementation would entail. Do you know if there
> have been any attemplted implementations, and if they have worked even
> remotely well?

There is an implementation which lives at the CMU AI repository.  It
does work but it's not completely ANSI -- it uses things like
COMPILER-LET.  It also has subtle type bugs which can break it on some
implementations -- it does things like:

	(let (x)
	  (declare (type <something-not-including-nil> x))
	  (setf x <instance of type>)
          ...)

which makes CMUCL (and, bizarrely, Genera in the case of array types)
very unhappy.  I spent some time trying to understand it well enough
to change it to raise the SETFs into the LET, but it was too hard for
me.

--tim
	  
From: Raymond Toy
Subject: Re: Simplified LOOP
Date: 
Message-ID: <4n67movnvd.fsf@rtp.ericsson.se>
Tim Bradshaw <···@aiai.ed.ac.uk> writes:

> There is an implementation which lives at the CMU AI repository.  It
> does work but it's not completely ANSI -- it uses things like
> COMPILER-LET.  It also has subtle type bugs which can break it on some
> implementations -- it does things like:
> 
> 	(let (x)
> 	  (declare (type <something-not-including-nil> x))
> 	  (setf x <instance of type>)
>           ...)
> 
> which makes CMUCL (and, bizarrely, Genera in the case of array types)
> very unhappy.  I spent some time trying to understand it well enough
> to change it to raise the SETFs into the LET, but it was too hard for
> me.
> 

The version at www.cons.org has some (all?) of these fixed, by either
making sure that X is initialized correctly or by relaxing the type
declaration. 

If www.cons.org doesn't have these fixed, I have a version that fixes
them all (I think).

Ray
From: Bj�rn Remseth
Subject: Re: Simplified LOOP
Date: 
Message-ID: <34DF34E4.C14DDBEF@forut.telenor.no>
Bruno Haible wrote:


> Even better is to decouple COLLECT from LOOP altogether. Just the
> same way as PROG has been successully split into LET, BLOCK and
> TAGBODY, the COLLECT part can be taken out from LOOP. This has the
> added benefit that it can be used without any looping.

Best suggestion so far in this thread!

								(Rmz)