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

New Error Proposal



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