Number: 2071

Date:  6-Sep-84 08':52':47

Submitter: Masinter

Source: Masinter

Subject: want Catch/Throw, named LAMBDAs & progs, etc. in Interlisp-D

Assigned To: 

Attn: JonL

Status: Open

In/By: 

Problem Type: 

Impact: 

Difficulty: 

Frequency: 

Priority: 

System: 

Subsystem: 

Machine: 

Disk: 

Lisp Version:  5-Sep-84 16':37':47

Source Files: 

Microcode Version: 5124

Memory Size: 4096

File Server: 

Server Software Version: 

Disposition: 

Description: [this may be in CMLSPECIALFORMS, but I thought I would preserve this discussion here':'
'
Date': 16 Feb 1982 0959-PST'
From': Neil Goldman <GOLDMAN at USC-ISIF>'
Subject': Re': AP statistics'
To': Masinter at PARC-MAXC'
In-Reply-To': Your message of 12-Feb-82 1748-PST'
'
Your NAMEDLAMBDA would allow me to get the effect I get now with my SETSTKNAME (provided you had both NAMEDLAMBDA and NAMEDNLAMBDA). But there are two alternatives which would be preferable, from my viewpoint':'
'
1) Generalization of the lambda (under some other name, of course) to something akin to the lisp machine notion of a lambda list, where I can specify for each formal parameter':  '
   a) how it is to be passed (quote the actual, eval the actual, or   (this is not provided by the lisp machine) some other function'
   b) whether a formal parameter is optional, and, if so, how to  initialize it if no actual is provided'
'
2) Simply allowing me some way of distinguishing, inside a function, whether an actual parameter was provided or not.  The rule of universally binding "excess" formals to NIL in interlisp, i think, was a very bad choice;  the empty list is simply too important a value to be co-opted for this purpose -- i.e., the fact that the formal is initially NIL'
can''t be assumed to indicate that the actual was defaulted.  It is because of this that I had to translate my  (APLAMBDA (F1 ... Fn) ...)'
   into (NLAMBDA X (PROG (F1 ... Fn) ...]  instead of simply'
    (NLAMBDA (F1 ... Fn) ...]'
    and get into the setstkname stuff.'
'
I suppose (1) is too major an effort to consider.  Conceivably (2) could be done by means of some hack without too much difficulty -- e.g., a  function-specific declaration which EVAL, APPLY and the compiler were sensitive to.  Doing it right might also be a major effort.'
'
neil'
********************'
'
Mail-from': Arpanet host USC-ISIF rcvd at 7-APR-82 1252-PST'
Date':  7 Apr 1982 1245-PST'
From': Neil Goldman <GOLDMAN at USC-ISIF>'
Subject': getting close'
To': masinter at PARC-MAXC'
cc': goldman at USC-ISIF'
'
I''ve been able to use /CALLME as an interim solution until some form of your "named" frame construct becomes available.  I have 1 observation and 1 question':'
'
OBSERVATION':'
APPLY and APPLY* are not equivalent with respect to merging of frames. In particular,'
 (APPLY* (FUNCTION (LAMBDA (X Y) (\CALLME ''FOO) ... )) ...)'
did not give me a new frame when compiled, and ended up with an outer frame being named FOO, whereas the analogous APPLY did produce a separate frame named FOO.  (It would be slightly more efficient in my application to use APPLY* that APPLY, since the arguments are not already in a list, but I will convert to the named frame construct as soon as it is available anyway.'
'
QUESTION':'
Is it correct that, as things stand now, there is no reasonable way for me to implement my CATCH/THROW like construct -- that is, the only way to get distinct frame for the CATCH, with a name I can specify,'
is to introduce an APPLY -- e.g.,'
(CATCH ERRORCLASS <form>) ===>'
  (APPLY (FUNCTION (LAMBDA NIL (\CALLME ''ERRORCLASS) <form>)) NIL)'
which works, but requires all variables used freely in <form> to be made special, even if they are bound in a PROG or LAMBDA in which the CATCH is lexically enclosed.'
'
In particular, whatever you do to make NLSETQ work without '
requiring variables to be declared special goes beyond anything I can accomplish with ordinary macros??'
'
neil'
 Catch and Throw'
To': MASINTER at PARC-MAXC'
'
Here is a version of CATCH* and THROW* (lisp machine style versions of catch and throw).  They seem to work correctly in INTERLISP-10.  I would appreciate your comments, especially if it does something terrible. Included is a macro, RESETLST*, like RESETLST, but it knows about catch*'
and throw*.  There are backquoted and un-backquoted versions.'
'
Here is the backquoted version.'
'
(PUTPROP ''CATCH* ''MACRO'
''(ARGS `((LAMBDA (/CatchLabel)'
	   (SETSTKNAME -1 ''CATCH*)'
	   ,(CADR ARGS))'
	 ,(CAR ARGS))))'
'
'
'
(DEFINEQ'
  (THROW* (LABEL VALUE POS)'
	  (* CATCH* and THROW* interact properly with RESETLST*'
	     only if thrown through the last form of the RESETLST* args.)'
	  (OR POS (SETQ POS (STKSCAN ''THROW*)))'
	  (PROG ()'
	    LOOP'
	    (SETQ POS (STKNTH -1 POS POS))'
	    (OR POS (ERROR LABEL "No pending CATCH* for this label"))'
	    (SELECTQ (STKNAME POS)'
	      (CATCH*'
	       (COND ((OR (NULL LABEL)'
			  (EQ LABEL (STKARG ''/CatchLabel POS)))'
		      (RETFROM POS VALUE T))))'
	      (RESETLST*'
	       (RETTO POS (LIST ''/CatchLabel LABEL VALUE) T))'
	      NIL)'
	    (GO LOOP))))'
'
'
(PUTPROP ''RESETLST* ''MACRO'
	 ''(ARGS `(PROG ((VAL (RESETLST @,(DREVERSE (CDR (REVERSE ARGS)))'
				       ((LAMBDA ()'
					  (SETSTKNAME -1 ''RESETLST*)'
					  ,(CAR (FLAST ARGS)))))))'
		   (COND ((AND (LISTP VAL)'
			       (EQ (CAR VAL) ''/CatchLabel))'
			  (THROW* (CADR VAL) (CADDR VAL)))'
			 (T (RETURN VAL))))))'
'


Workaround: 

Test Case: 

Edit-By: 

Edit-Date: