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

Re: KMP's proposal



> ....  What may be controversial is letting a more general
>handler established in an inner condition-bind override a more specific
>handler established farther out.  I think it should work this way, as I
>said in my earlier note, but I'm not sure what the Lisp Machine does or
>what KMP was proposing.

What you want will work on the Lisp Machine. The handler established
in an inner condition-bind whether defined for a general condition
name (like ERROR) or specific condition-name (like FILE-NOT-FOUND)
will overide any handler (specific or general) established farther
out, as long as the condition signalled has a condition name which
matches the one defined for the handler.  (eg, condition
FILE-NOT-FOUND might have condition names FILE-ERROR and ERROR)

>Is a special piece of machinery really needed for this (restart handlers)?  
>Couldn't this be handled easily by Condition-case, with one or more
>of the clauses being a throw to some appropriate outer catch?  Or am
>I missing something? 

CONDITION-CASE would work if you want to ALWAYS do the throw whenever
the particular condition was signalled.  With CONDITION-CALL you could
also test a predicate before deciding to do the throw.  On the Lisp
Machine, a restart handler defines a proceed type which does a throw
to some appropriate outer catch. Restart handlers aren't condition
handlers.  Maybe restart handler is the wrong name.  If a debugger or
condition handler asks for a list of proceed-types, it should include
the ones defined by the restart handlers.  If in the debugger, you
can choose one of these restart proceed types.

What I would like to see is somthing like KMP's special form
(CATCH-ABORT form).  But allow one to define it for a specific
condition-name.

 (CATCH-CONDITION-RESTART
       (CONDITION-NAMES  FORMAT-STRING FORMAT-ARGS...)
      BODY)

 CATCH-CONDITION-RESTART executes body.  If condition-name is
signalled, and this restart is selected, return NIL as the first value
and Non-Nil as the second value.  If this condition is not signalled,
return the value of the last form in body.  FORMAT-STRING and
FORMAT-ARGS is used to describe the restart (eg, "Return to top-level").

(CONDITION-RESTART
  (CONDITION-NAMES FORMAT-STRING FORMAT-ARGS...)
    BODY)

 CONDITION-RESTART executes body.  If condition-name is signalled and
this restart is selected, BODY is executed again from the beginning.
If BODY returns, the values of the last form in it are returned from
CONDITION-RESTART.

Most command-loops would use this with condition-names ABORT and ERROR.

> Can you supply an example where this (classifying conditions or
> proceed options) is needed?  The simpler we keep
> this, the easier it is going to be to come up with something usable.

Classifying conditions allows handlers flexibility in deciding which
conditions they will handle.  A handler might be defined for all
errors or a specific file errors.  You can do this with KMP's proposed
special form DEFINE-SIMPLE-CONDITION.  For example,

(DEFINE-SIMPLE-CONDIITON  FILE-NOT-FOUND (file-name) (FILE-ERROR ERROR)
   (format t "File ~A not found"  file-name))   

Classifying proceed options could also allow more flexibility.  One
proceed type could be recognized as a substitute for another proceed
type.  DEFINE-PROCEED-TYPE could include another optional arg PARENT.


> The common lisp functions ERROR and CERROR should include a
>   signal-name (condition-type) argument.
> I agree.  It's not obvious to me where such an argument can be inserted
> in a compatible way, however.

My proposal:
 (ERROR condition-name format-string &rest format-args)

 (CERROR proceed-type condition-name format-string format-args)
 This replaces CERROR's CONTINUE-FORMAT-STRING with PROCEED-TYPE.
A DEFINE-PROCEED-TYPE for proceed-type whould contain the
CONTINUE-FORMAT-STRING.


For those not having access to a the Lisp Machine document, here are
the definitions of the special forms I think we should include:

(CONDITION-CASE (var1 var2 ....)
  body
    (condition-name-1  forms...)
    (condition-name-2  forms..)
    (error             forms ...)  ;; for all conditions which are errors
    (:no-error     forms ...)  
   ....)

This establishes a handler which selects one of its clauses to execute
by comparing condition-name to the condition actually signaled.  The
values of the last form in the clause are returned.  VAR1 is bound to
the condition-object which was signaled.  In the :NO-ERROR clause,
VAR2, etc.. are bound to the values returned by BODY before executing
the :no-error forms.

(CONDITION-CALL  (var1 var2 ...)
   body
    (pred-1  handler-forms....)
    (pred-2  handler-forms ...)
   .....)

The difference between this and CONDITION-CASE is the predicate in
each clause.  The clauses in a condition-call resemble the clauses of
a COND rather than those of a CASE.

(CATCH-ERROR body ) 
 If an error occurs it returns two values, NIL and NON-NIL.  The second value
indicates the occurence of an error.  If no error occurs, it returns
the value(s) of the last form in body.

(IGNORE-ERRORS body)
 If an error occurs inside BODY, the first value returned is NIL and
the second is NON-NIL.  If no error occurs, the first value returned
is the first return value of the last form in BODY and the second
value is NIL.

-------