From: Drew Justin Asson
Subject: Using LOOP macro
Date: 
Message-ID: <ASSON.93Apr6083518@chacmool.stsci.edu>
I've seen a great deal of people arguing on both sides of the issue.
LOOP is a very powerful extension to Common LISP, even though it often
throws out the syntacic flavor of LISP.  Some people have argued that it
makes code harder to read.  It some cases that is true ... I've looked at
LOOP code that goes on for 1/2 - 1 full page and it takes me a while to sort
it out.  But, then again, I've read and written code that is very readable
using LOOP, and atleast with my programming skills, would have looked awful
using DO, etc.

LOOP provides a nice meta-way of describing an algorithm and leaves it up
to the implementation to turn it into good code.  This is one thing that LISP
was always said to do: remove the worry of implementation details (such as
memory management, list mechanisms, etc) from the developer.  Let the developer
concentrate on higher order things.

-- Drew
--
==========================================================================
| Drew J. Asson                     |  Space Telescope Science Institute |
| AI Senior Software Engineer       |  3700 San Martin Drive             |
| Advance Planning Systems Branch   |  Baltimore, MD  21218, USA         |
| Internet: ·····@stsci.edu         |  (410) 338-4474   [338-1592 (fax)] |
==========================================================================

From: Skip Egdorf
Subject: Re: Using LOOP macro
Date: 
Message-ID: <EGDORF.93Apr8110814@zaphod.lanl.gov>
In article <··················@chacmool.stsci.edu> ·····@chacmool.stsci.edu (Drew Justin Asson) writes:
   I've seen a great deal of people arguing on both sides of the issue.
   LOOP is a very powerful extension to Common LISP, even though it often
   throws out the syntacic flavor of LISP.  Some people have argued that it
   makes code harder to read.  It some cases that is true ... I've looked at
   LOOP code that goes on for 1/2 - 1 full page and it takes me a while to sort
   it out.  But, then again, I've read and written code that is very readable
   using LOOP, and atleast with my programming skills, would have looked awful
   using DO, etc.

I've avoided entering this particular religious debate, but I feel
that an important point that is being left out of the discussion is
hinted at above when the writer notes that loop "often throws out the
syntactic flavor of LISP."

Early religious wars debating Unix vs everything-else often zeroed in
on the not-so-user-friendly nature of some of the commands: "Why does
Unix's 'ls' command just print a list of file names? I like my XYZ
computer's 'files' command that prints nice greetings to me before the
file list and prints flowery summaries after the file list."

This totally missed the point that one of the main powers of Unix was
its ability to allow the user to combine commands with pipes. The
output of 'ls' was primarily designed to produce output FOR OTHER
PROGRAMS connected with a pipe.

Similarly, one of the major strengths of Lisp is that programs are
represented in the common data form processed by the language. It is
easy and common to write Lisp programs that examine other Lisp
programs. Often, the only structure needed is to examine the CAR of a
list for the function, macro, or special form, and then look at it
arguments recursively. The biggest problem with loop is that it does
not fit this framework well. Loop needs a bunch of parsing of its
internal structure by such a program analyzing program in order to see
what is going on.

I believe that this is at the root of the loop flame fest. The
objection is not to iteration per se; rather the objection is to the
insertion of a bit of the Cobol compiler into Lisp. The objection
might be bluntly worded "If you want to write Lisp, then write Lisp.
If you want to write Cobol, then please go somewhere else."

				Skip "flamebait" Egdorf
				···@lanl.gov
From: Drew Justin Asson
Subject: Re: Using LOOP macro
Date: 
Message-ID: <ASSON.93Apr8134526@chacmool.stsci.edu>
On Thu, 8 Apr 1993 18:08:14 GMT, ······@zaphod.lanl.gov (Skip Egdorf) said:

> [stuff deleted]

>Similarly, one of the major strengths of Lisp is that programs are
>represented in the common data form processed by the language. It is
>easy and common to write Lisp programs that examine other Lisp
>programs. Often, the only structure needed is to examine the CAR of a
>list for the function, macro, or special form, and then look at it
>arguments recursively. The biggest problem with loop is that it does
>not fit this framework well. Loop needs a bunch of parsing of its
>internal structure by such a program analyzing program in order to see
>what is going on.

>I believe that this is at the root of the loop flame fest. The
>objection is not to iteration per se; rather the objection is to the
>insertion of a bit of the Cobol compiler into Lisp. The objection
>might be bluntly worded "If you want to write Lisp, then write Lisp.
>If you want to write Cobol, then please go somewhere else."

>				Skip "flamebait" Egdorf
>				···@lanl.gov

I agree with what you said re: unix and ls.  I'm very fond of the modular
style with which it was written.  (don't get me wrong, I don't think unix
is the be-all-end-all!)

As to what you said about being able to analyze lisp code with some piece
of lisp code, you mentioned that all you need to do is to look at the
car of a list and tell whether it is a function, special form, or a 
MACRO.  Macros, by definition, have unusual forms, that is why they are
macros.  (By macros, I mean the macro example, not the macro definition
(i.e. defmacro)).  LOOP is a macro, albeit incredible huge and hard to read,
but it is, nonetheless a macro.  When one encounters a macro, just 
macroexpand it, then analyze it.

This isn't meant to say loop must be used, but that it should be available
as a tool
.. Drew
--
==========================================================================
| Drew J. Asson                     |  Space Telescope Science Institute |
| AI Senior Software Engineer       |  3700 San Martin Drive             |
| Advance Planning Systems Branch   |  Baltimore, MD  21218, USA         |
| Internet: ·····@stsci.edu         |  (410) 338-4474   [338-1592 (fax)] |
==========================================================================
From: Daniel LaLiberte
Subject: Re: Using LOOP macro
Date: 
Message-ID: <LIBERTE.93Apr9150317@ebony.cs.uiuc.edu>
   From: ·····@chacmool.stsci.edu (Drew Justin Asson)

   LOOP is a macro, albeit incredible huge and hard to read,
   but it is, nonetheless a macro.  When one encounters a macro, just 
   macroexpand it, then analyze it.

Macroexpanding may be OK for analysis, but it is not sufficient for
source level debugging, another kind of processing that the usual Lisp
syntax makes pretty easy.  For this application, it is necessary to
know where the evaluatable expressions are *before* macroexpansion.  

I developed a source level debugger for Emacs Lisp, and have extended
it to handle many of the Common Lisp macros as well.  When it came to
loop, I not only had to add new features for how macro arguments are
specified, which was good because these features applied elsewhere
too, but I had to write a relatively huge specification that to me
makes it obvious that something is wrong.  I include the spec below.

Another thing that is made more difficult by loop's lack of parens is
automatic indenting by editors like Emacs.

Dan LaLiberte
·······@cs.uiuc.edu
(Join the League for Programming Freedom: ···@uunet.uu.net)
-------------

;; First, here is the relatively simple spec for do,
;; not that it is claimed to do as much as loop.
(def-edebug-spec do
  ((&rest &or symbolp
	  (symbolp &optional form form))
   (form body) body))


;; The rest is the multiple part spec for loop.
(def-edebug-spec loop
  ([&optional ["named" symbolp]]
   [&rest 
    &or
    ["repeat" form]
    loop-for-as

    ["with" loop-var
     loop-type-spec
     [&optional ["=" form]]
     [&rest ["and" loop-var
	     loop-type-spec
	     [&optional ["=" form]]]]]
		   
    loop-initial-final]
   [&rest loop-clause]
   ))

(def-edebug-spec loop-for-as
  ([&or "for" "as"] loop-for-as-subclause
   &rest ["and" loop-for-as-subclause]))

(def-edebug-spec loop-for-as-subclause
  (loop-var 
   loop-type-spec
   &or 
   [[&or "in" "on"] form &optional ["by" function]]
   ["=" form &optional ["then" function]]
   ["across" vectorp]
   ["being" 
    [&or "each" "the"]
    &or
     [[&or "hash-key" "hash-keys"
	   "hash-value" "hash-values"]
      [&or "in" "of"] hash-table-p
      &optional ["using" ([&or "hash-value" "hash-key"] sexp)]]
					
     [[&or "symbol" "present-symbol" "external-symbol"
	   "symbols" "present-symbols" "external-symbols"]
      [&or "in" "of"] package-p]
     
     ;; Extensions for Emacs
     [[&or "extent" "extents"
	   "screen" "screens"
	   "window" "windows"] [&or "in" "of"] form]
     [[&or "key-code" "key-codes"
	   "key-binding" "key-bindings"] ;??
      ]]
   ;; arithmetic - must be last since all parts are optional
   [[&optional [[&or "from" "downfrom" "upfrom"] form]]
    [&optional [[&or "to" "downto" "upto" "below" "above"] form]]
    [&optional ["by" form]]
    ]))

(def-edebug-spec loop-initial-final
  (&or ["initially" &rest loop-non-atomic-expr]
       ["finally" &or [[&optional [&or "do" "doing"]] 
			&rest loop-non-atomic-expr]
		       ["return" form]]))

(def-edebug-spec loop-and-clause
  (loop-clause &rest ["and" loop-clause]))

(def-edebug-spec loop-clause
  (&or
   [[&or "while" "always" "never" "thereis"] form]
     
   [[&or "collect" "collecting"
	 "append" "appending"
	 "nconc" "nconcing"] form 
	 [&optional ["into" loop-var]]]

   [[&or "count" "counting"
	 "sum" "summing"
	 "maximize" "maximizing"
	 "minimize" "minimizing"] form
	 [&optional ["into" loop-var]]
	 loop-type-spec]

   [[&or "if" "when" "unless"]
    form loop-and-clause
    [&optional ["else" loop-and-clause]]
    [&optional "end"]]

   [[&or "do" "doing"] &rest loop-non-atomic-expr]

   ["return" form]
   loop-initial-final
   ))

(def-edebug-spec loop-non-atomic-expr
  ([[&not atom] form]))

(def-edebug-spec loop-var
  (&or symbolp (loop-var . [&or loop-var nil])))

(def-edebug-spec loop-type-spec
  (&optional ["of-type" loop-d-type-spec]))

(def-edebug-spec loop-d-type-spec
  (&or typep (loop-d-type-spec &rest loop-d-type-spec)))
From: Drew Justin Asson
Subject: Re: Using LOOP macro
Date: 
Message-ID: <ASSON.93Apr8141920@chacmool.stsci.edu>
On Thu, 8 Apr 1993 18:08:14 GMT, ······@zaphod.lanl.gov (Skip Egdorf) said:

> [stuff deleted]

>Similarly, one of the major strengths of Lisp is that programs are
>represented in the common data form processed by the language. It is
>easy and common to write Lisp programs that examine other Lisp
>programs. Often, the only structure needed is to examine the CAR of a
>list for the function, macro, or special form, and then look at it
>arguments recursively. The biggest problem with loop is that it does
>not fit this framework well. Loop needs a bunch of parsing of its
>internal structure by such a program analyzing program in order to see
>what is going on.

>I believe that this is at the root of the loop flame fest. The
>objection is not to iteration per se; rather the objection is to the
>insertion of a bit of the Cobol compiler into Lisp. The objection
>might be bluntly worded "If you want to write Lisp, then write Lisp.
>If you want to write Cobol, then please go somewhere else."

>				Skip "flamebait" Egdorf
>				···@lanl.gov

I agree with what you said re: unix and ls.  I'm very fond of the modular
style with which it was written.  (don't get me wrong, I don't think unix
is the be-all-end-all!)

As to what you said about being able to analyze lisp code with some piece
of lisp code, you mentioned that all you need to do is to look at the
car of a list and tell whether it is a function, special form, or a 
MACRO.  Macros, by definition, have unusual forms, that is why they are
macros.  (By macros, I mean the macro example, not the macro definition
(i.e. defmacro)).  LOOP is a macro, albeit incredible huge and hard to read,
but it is, nonetheless a macro.  When one encounters a macro, just 
macroexpand it, then analyze it.

This isn't meant to say loop must be used, but that it should be available
as a tool
.. Drew
--
==========================================================================
| Drew J. Asson                     |  Space Telescope Science Institute |
| AI Senior Software Engineer       |  3700 San Martin Drive             |
| Advance Planning Systems Branch   |  Baltimore, MD  21218, USA         |
| Internet: ·····@stsci.edu         |  (410) 338-4474   [338-1592 (fax)] |
==========================================================================