[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Writing PROG as a macro



I agree whole-heartedly with your suggestion that (PROG T ...) be replaced with
the requirement that named RETURNs match only named PROGs and un-named 
RETURNs match un-named PROG. I have always felt the special-casing of 
T to be inelegant and I think this offers just the right degree of
control.

Also, since you brought up the idea of lower level primitives to implement
PROG with, I dredge up here thoughts I presented on the subject years back...

-----Begin Forwarded Message Portions-----
Date: Sun, 13 Apr 1980 00:54:00 -0000
From: KMP at MIT-MC (Kent M. Pitman)
Subject: What should we DO?
To: (BUG LISP) at MIT-MC, NIL at MIT-MC, (BUG LISPM) at MIT-MC
CC: H at MIT-MC, KMP at MIT-MC, HENRY at MIT-MC, RMS at MIT-MC
CC: MOON at MIT-MC

... I now present my feelings on this issue of how DO/PROG could be done in
order this haggling, part of which I think comes out of the fact that these
return tags are tied up in PROG-ness and so on ... Suppose you had the
following primitives in Lisp:

(PROG-BODY ...) which evaluated all non-atomic stuff. Atoms were GO-tags.
 Returns () if you fall off the end. RETURN does not work from this form.

(PROG-RETURN-POINT form name) name is not evaluated. Form is evaluated and
 if a RETURN-FROM specifying name (or just a RETURN) were executed, control
 would pass to here. Returns the value of form if form returns normally or
 the value returned from it if a RETURN or RETURN-FROM is executed. [Note:
 this is not a [*]CATCH because it is lexical in nature and optimized out
 by the compiler. Also, a distinction between NAMED-PROG-RETURN-POINT
 and UNNAMED-PROG-RETURN-POINT might be desirable -- extrapolate for yourself
 how this would change things -- I'll just present the basic idea here.]

(ITERATE bindings test form1 form2 ...) like DO is now but doesn't allow
 return or goto. All forms are evaluated. GO does not work to get to any form
 in the iteration body.

So then we could just say that the definitions for PROG and DO might be
(ignore for now old-DO's -- they could, of course, be worked in if people
really wanted them but they have nothing to do with this argument) ...

 (PROG [ <tag> ] <bvl> . <body>)

  => (PROG-RETURN-POINT (LET <bvl> (PROG-BODY . <body>)) [ <tag> ])

 (DO [ <tag> ] <bind-specs> <tests> . <body>)

  => (PROG-RETURN-POINT (ITERATE <bind-specs> <tests> (PROG-BODY . <body>))
			[ <tag> ])

Other interesting combinations could be formed by those interested in them.
If these lower-level primitives were made available to the user, he needn't
feel tied to one of PROG/DO -- he can assemble an operator with the 
functionality he really wants....
-----
Date: Tue, 15 Apr 1980 04:40:00 -0000
From: "Guy L. Steele, Jr." <GLS at MIT-MC>
Subject: What should we DO?
To: BUG-LISP at MIT-MC, NIL at MIT-MC, BUG-LISPM at MIT-MC
cc: KMP at MIT-MC, H at MIT-MC, HENRY at MIT-MC, RMS at MIT-MC,
    MOON at MIT-MC

... Seriously, folks, my own position on DO and friends is largely in agreement
with KMP here.  His PROG-RETURN-POINT is simply the lexical catch advocated
by DLW, with allowances for how RETURN could be expressed in terms of that.
It is of interest to note that the S-1 NIL compiler in fact
implements a construct called PROG-BODY with precisely those semantics;
PROG is then turned into a nested LET and PROG-BODY.  This was done
to concentrate all knowledge of variable bindings into one place --
the code that handles LAMBDA.  The original intent was just to use
this construct internally to the compiler, but indeed it may be a useful
building-block for other macros.
-----End Forwarded Message Portions-----