[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
New Error Proposal
- To: Moon @ SCRC-TENEX
- Subject: New Error Proposal
- From: Kent M. Pitman <KMP @ MIT-MC>
- Date: Wed, 11 May 1983 09:59:00 -0000
- Cc: Common-Lisp @ SU-AI
The new error proposal looks mostly good. A few remarks, though...
* Based on heavy experience with the old and new error system, I feel
strongly that one consistent irritation of the old system was that
it didn't clearly distinguish between the cause and correction of
an error and that CERROR as currently proposed will perpetuate that
problem. eg, when you ran with error messages turned on but errors
ignored, typeout like "continuing will do such-and-so" was at least
irritating and frequently wrong. I put out for discussion the idea
that the CERROR should be modified as follows...
CERROR format-string-1 format-string-2 &rest args
Signal an error, with the message constructed by applying FORMAT to
format-string-1 and the arguments. If the debugger is entered, it
may choose to offer a message composed by calling FORMAT on
format-string-2 and the arguments, describing what will happen if
the error is proceeded. Continuing from such an error will cause
CERROR to return NIL. Use CERROR rather than ERROR to signal
errors for which you have written recovery code. The name stands
for "continuable error," which is too verbose to use for such a
common function.
Examples:
(UNLESS (= (LIST-LENGTH FORM) 3)
(CERROR "Wrong number of arguments in ~S"
"~1G:~[Ignore extra args~;Assume 0 for missing args~]."
FORM (< (LIST-LENGTH FORM) 3))
(SETQ FORM (APPEND FORM '(0 0))))
(DO () ((KNOWN-WORDP X) X)
(CERROR "~S is unknown, probably misspelled."
"Replace ~S and try again." X)
(FORMAT T "~&New word: ")
(SETQ X (READ)))
* It occurs to me that the naming of CTYPECASE and ETYPECASE might
be solved in a completely different way. Rather than adding new
special forms, one could make several kinds of otherwise clauses.
The argument against this might be that it means more special cases of
symbols in the case-list position, making that position more visually
ambiguous. The counter-argument (held by some (eg, me)) is that people
should use parens around everything but the otherwise options anyway.
Examples:
(SETQ X 1/3)
(TYPECASE X
((INTEGER) (- X))
((SYMBOL) (INVERSE X))
(:OTHERWISE-ERROR))
Error: The value of X, 1/3, was neither an integer nor a symbol.
(TYPECASE X
((INTEGER) (- X))
((SYMBOL) (INVERSE X))
(:OTHERWISE-CERROR))
Error: The value of X, 1/3, was neither an integer nor a symbol.
Entering Debugger. Options:
Meta-A: Store a new value in X and retry erring code.
Meta-B: Return to Lisp toplevel.
Meta-C: Logout
>> Meta-A
New Value for X: 9
-9
* I liked your stating explicitly not to put "Error: " at the head of
error messages. I would further like it specified that multi line error
messages should not be padded (with spaces, ";", etc.) because tools such
as the debugger (or whatever) will take care of padding lines with the
appropriate text.
(ERROR (FORMAT NIL "FOO~%BAR"))
should print out as:
>>Error: FOO
BAR
not as
>>Error: FOO
BAR
Ditto for the continuation string. The LispM currently has the bug
that proceed options come out as:
s-A: This is a proceed option
extending over multiple lines.
s-B: This is another.
when
s-A: This is a proceed option
extending over multiple lines.
s-B: This is another.
would be better. Note that (ERROR (FORMAT NIL "FOO~% BAR"))
would want to come out like
>>Error: FOO
BAR
The reason for guaranteeing something like this is that users will frequently
see the error coming out only in the debugger and may feel an urge to write
(ERROR (FORMAT "FOO~%~16TBAR")) or some such so it'll look pretty. If another
program gets ahold of such a format string and tries to use it elsewhere,
though, it'll look like garbage. Better the user should just be told flat out
that "any necessary padding for continuation lines will be taken care of". eg,
I have seen Maclisp code where users did:
(ERROR (FORMAT NIL "FOO~%;BAR"))
since they knew that the first line would have a leading ";" and the rest
would not. If the error message style is with leading, that should be supplied
on line 1 and on continuation lines by the system.
This also takes care of people who try to assume that line 1 will be shorter
than subsequent lines because they know a 20 character leader will occur on
that line and tends to produced multi-line messages where lines have balanced
lengths, rather than multi-line messages where the first line is considerably
shoerter than subsequent lines.
* I don't see any reason why
(ABORT-PROGRAM)
can't be a synonym for what the LispM calls (SIGNAL 'SYS:ABORT). This
is a pretty useful thing to put on interrupt characters. All you have to
do is add an additional special form
(CATCH-PROGRAM-ABORTS ...) or some such which does
(CONDITION-CASE ()
(PROGN ...)
(SYS:ABORT ...))
on the LispM. In a Lisp where conditions didn't exist, people could do
the equivalent with CATCH/THROW.
In fact, I don't know why just ABORT and CATCH-ABORT aren't adequate names.
I find the word "program" ambiguous on a mainframe between meaning the
toplevel form I invoked in my read-eval-print loop and the exec command I
used to invoke the Lisp. (ie, the c-Abort vs c-m-Abort distinction on the
LispM).
In any case, I think these are valid kinds of issues for programmers to
want to do in a machine independent fashion and should be included.
* In things like CHECK-ARG, etc. I see no reason their forms shoudln't be
evaluable multiple times. It's essential that it be clearly documented,
but that's easy to do. In the rare case that multiple evaluation would be
a screw, a simple LET will probably fix the user's problem. If we later
find out it's easy to guarantee single evaluation, it's easier to relax
things and tell him so than it is to go the other route if people have
written code depending on single evaluation.
--kmp