[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: LOOP loses
- Subject: Re: LOOP loses
- From: Kent M. Pitman <KMP at MIT-MC>
- Date: Tue ,18 Nov 80 18:54:00 EDT
I side with those that feel LOOP is a big mistake to put into Lisp in
its current form.
CWH's arguments about the parenthesizing are a valid criticism of LOOP in
their own right. I agree with him completely and have little to add on that
area. I will try here confine myself to gripes of a different nature
-- to do with semantics, rather than syntax ...
The day may come in which we can program in English and be understood,
but it's not here yet. I believe LOOP unfairly deludes a person into
thinking that if it reads well in English, it's going to run. LOOP is a
game between the programmer and the LOOP macro code. Sometimes it gets
things right. If you're lucky, you even have a good enough model of
what's going on to figure out when it'll guess right and when it won't.
You're lucky you have that good a model ... What about those poor people
who don't have such a good model and don't know what LOOP will win the
game on and what cases it will bomb on. I somehow feel you're doing them
a dis- service by introducing such a DWIM-ish hack into Maclisp and I
wish you'd leave loop as a cute package on LIBLSP; that people can load
iff they are willing to take the responsibility for what it does to
them.
Facilities with the power of LOOP certainly need to be devised, but they
oughtn't be `endorsed' (which is my opinion of what AUTOLOAD'ing is) until
people are happier with their syntax and semantics. I am satisfied with
neither.
Here are some samples of the sort of things that bother me about it. Some
(maybe most) are clearly bugs in the particular implementation, but I include
them anyway because I think that the fact that certain classes of bugs arise
at all gives useful insight into the nature of the beast we are playing
with ... Indeed, some only serve to characterize a larger problem which
I couldn't begin to exhaustively list all of the obscure manifestations of...
[a] It requires a hairy parser, and its error messages are correspondingly
heuristic and confusing.
(LOOP FOR X TO 3 FROM 4 DO (PRINT X))
;TO unknown keyword in FOR/AS clause
;BKPT *RSET-TRAP
(LOOP FOR X FROM 3 TO 4 DO PRINT X)
;X unknown keyword in LOOP
;BKPT *RSET-TRAP
Here (LOOP FOR X FROM 3 TO 4 DO (PRINT X)) was desired. The error
diagnostic is way offbase. [And by the way, implementors, that shouldn't
be a *RSET break. Use a real error channel, please? Thanks.]
(LOOP FROM 3 TO 5 DO 3)
;FROM unknown keyword in LOOP
This error message is totally confusing. FROM *is* a LOOP keyword,
it's just not allowed in LOOP-toplevel context. I guess my feeling is
that what the user saves in being able to write his code in this
concise way, he'll lose back partly in trying to decipher the error
messages, since they are considerably more obscure than the average
Lispy error message.
[b] Things which read right in English don't work.
(LOOP FOR X FROM 3 TO 5 DO COLLECT X)
;X unknown keyword in LOOP
(LOOP FOR X FROM 3 TO 5 DO (COLLECT X))
;COLLECT UNDEFINED FUNCTION OBJECT
Oops. Here I forgot that the English is only a magic illusion that
works in certain places. Having to remember NOT to use parentheses
may teach people bad habits about the rest of Lisp and will encourage
a poor programming style if they ever code their own macros.
[c] Two phrases which have equivalent English meanings and which are both
parsed by LOOP, do different things:
(LOOP FOR X FROM 3 TO 5 COLLECTING X)
(3 4 5)
(LOOP COLLECTING X FOR X FROM 3 TO 5)
(3 4 5 6)
Most proponents of LOOP I have spoken with cite its abilities to insulate
you from common fencepost erros as a feature. I'd rather not be deluded
into thinking I am safe if I'm really not.
[d] It doesn't constrain the way you order things sufficiently to avoid
all sorts of totally obscure interpretations:
(LOOP FOR X FROM 3 TO 5
COLLECT X
FOR X FROM 3 TO 5)
(3 5)
This sort of bug could easily arise from having mistyped a variable name.
Loop neither warns you that the interaction between the two X steppers
will be terrible, nor does it attempt to make sense of the interaction.
[e] Left-to-right order of evaluation is played with by LOOP in unpredictable
and dangerous ways:
(LOOP FOR X FROM (PROGN (PRINT 'FOO) 3) TO 5
DO (PRINT X)
FOR Y FROM (PROGN (PRINT 'BAR) X) TO 3
DO (PRINT Y))
FOO
BAR
3
3
4
NIL
Left-to-right evaluation of this form would demand something different.
The 3 should print before the BAR. I think LOOP is too unconstrained
and leaves itself open to unpredictability. I don't like guessing at
what it's going to do or trying to carry a model of its model of me. If
it can't understand what I mean in the way I say it, it should just
complain.
(LOOP FOR X FROM 3 TO 5 COLLECT X FOR X = (1- X))
;NIL NON-NUMERIC VALUE
;BKPT WRNG-TYPE-ARG
; X is bound to NIL. It died on the GREATERP check as seen here:
(LET ((X 3))
(DECLARE (FIXNUM X))
(LET (X)
(PROG (G0010 G0009)
(LOOP-COLLECT-INIT G0009 G0010)
NEXT-LOOP (AND (GREATERP X 5) (GO END-LOOP))
(RPLACD G0010 (SETQ G0010 (NCONS X)))
(SETQ X (1- X))
(SETQ X (1+ X))
(GO NEXT-LOOP)
END-LOOP (RETURN G0009))))
This occurs do to bad interaction in the two X steppers. Probably
such things should be invalid. Here's another case where order of
evaluation and dual steppers for the same variable are allowed but
do something some might find unintuitive at best:
(LOOP FOR X FROM 4 TO 100
UNTIL (NOT (ODDP X))
FOR X FROM 3 TO 100
DO (PRINT X))
3
5
7
...etc...
75
77
NIL
I'll leave it to you to hypothesize (or check) what this one expands
into.
[f] This one doesn't really count as a bug -- not much anyway; it can occur
in all kinds of code. It just looks especially bad in the LOOP formalism
because the usual Lisp parentheses divisions are missing ...
(SETQ TO 3 DO 5)
5
(LOOP FOR FROM FROM TO TO DO DO (PRINT FROM))
3
4
5
NIL