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

Issue: ERROR-CHECKING-IN-NUMBERS-CHAPTER (Version 1)



Well, no one else beat me to it so I finally got around to writing up one
of the several needed proposals on what functions should signal what errors.

Let me emphasize that even though this covers a subset of the functions in
CLtL, it is still both meaningful and useful to vote on it separately. If
we had only proposals for handling of errors in numbers and files/streams
that would cover a very large class of cases.

This being a long proposal, please keep your comments focused. Preferrably
just requests for specific changes in wording with a brief rationale for the
change. I am not firmly wedded to any of the positions I've taken here --
I just felt it necessary to take -some- position.  I patterned this pretty
directly after a document I passed out several meetings ago, but I got very
little feedback on that document, so I don't know if it was controversial.
 -kmp

----
Issue:        ERROR-CHECKING-IN-NUMBERS-CHAPTER
Forum:        Cleanup
References:   Numbers (pp193-232),
	      S:>kmp>cl>conditions>revision-18-notes.text.34
	      (formerly S:>kmp>cl-conditions.text.34),
Category:     CHANGE
Edit history: 06-Mar-89, Version 1 by Pitman
Status:       For Internal Discussion

Problem Description:

  In many cases, CLtL specifies ``is an error'' situations for functions
  in places that programmers would prefer to see an error signalled.

  Reliably signalling an error accomplishes two things...

   - It eases the development process by making it easier to notice errors
     in a timely fashion.

   - It makes it easier for code to reliably handle errors at runtime,
     leading to greater robustness in delivered applications.

Proposal (ERROR-CHECKING-IN-NUMBERS-CHAPTER:SCARECROW):        - a straw man...

 ABS should signal TYPE-ERROR if its argument is not type NUMBER.

 ACOS should signal TYPE-ERROR if its argument is not type NUMBER.
 ACOS might signal ARITHMETIC-ERROR.

 ACOSH should signal TYPE-ERROR if its argument is not type NUMBER.
 ACOSH might signal ARITHMETIC-ERROR.

 ASH should signal TYPE-ERROR if either argument is not type INTEGER.
 ASH might signal ARITHMETIC-ERROR.

 ASIN should signal TYPE-ERROR if its argument is not type NUMBER.
 ASIN might signal ARITHMETIC-ERROR.

 ASINH should signal TYPE-ERROR if its argument is not type NUMBER.
 ASINH might signal ARITHMETIC-ERROR.

 ATAN should signal TYPE-ERROR if exactly one argument is given and that
      argument is not type NUMBER.
 ATAN should signal TYPE-ERROR if exactly two arguments are given and
      either argument is not type (AND NUMBER (NOT COMPLEX)).
 ATAN might signal ARITHMETIC-ERROR.

 ATANH should signal TYPE-ERROR if its argument is not type NUMBER.
 ATANH might signal ARITHMETIC-ERROR.

 BOOLE should signal TYPE-ERROR if its first argument is not type
       (MEMBER #.BOOLE-CLR   #.BOOLE-SET   #.BOOLE-1    #.BOOLE-2
	       #.BOOLE-C1    #.BOOLE-C2    #.BOOLE-AND  #.BOOLE-IOR
	       #.BOOLE-XOR   #.BOOLE-EQV   #.BOOLE-NAND #.BOOLE-NOR
	       #.BOOLE-ANDC1 #.BOOLE-ANDC2 #.BOOLE-ORC1 #.BOOLE-ORC2)
 BOOLE should signal TYPE-ERROR if either its second or third
       argument is not type INTEGER.

 BYTE should signal TYPE-ERROR if either argument is not type INTEGER.

 BYTE-POSITION might signal TYPE-ERROR if its argument is not a byte
	       specifier (something that was returned by the BYTE
	       function). Note that byte specifiers are not required
	       to be disjoint from other types, so this error checking
	       is only heuristic.

 BYTE-SIZE might signal TYPE-ERROR if its argument is not a byte
	   specifier (something that was returned by the BYTE
	   function). Note that byte specifiers are not required
	   to be disjoint from other types, so this error checking
	   is only heuristic.

 CEILING should signal TYPE-ERROR if its first argument is not type
	 (AND NUMBER (NOT COMPLEX)).
 CEILING should signal TYPE-ERROR if its second argument is supplied
	 but is not type (AND NUMBER (NOT COMPLEX)).
 CEILING should signal DIVISION-BY-ZERO if its second argument is
	 supplied and is zero.
 CEILING might signal ARITHMETIC-ERROR.

 COMPLEX should signal TYPE-ERROR if its first argument is not type
	 (AND NUMBER (NOT COMPLEX)).
 COMPLEX should signal TYPE-ERROR if its second argument is provided
	 but is not type (AND NUMBER (NOT COMPLEX)).

 CONJUGATE should signal TYPE-ERROR if its argument is not type NUMBER.

 CIS should signal TYPE-ERROR if its argument is not type
     (AND NUMBERP (NOT COMPLEX)).
 CIS might signal ARITHMETIC-ERROR.

 COS should signal TYPE-ERROR if its argument is not type NUMBER.
 COS might signal ARITHMETIC-ERROR.

 COSH should signal TYPE-ERROR if its argument is not type NUMBER.
 COSH might signal ARITHMETIC-ERROR.

 DECF might signal SYNTAX-ERROR at semantic processing time.
 DECF should signal TYPE-ERROR at runtime if the variable to be
      incremented does not have a value of type NUMBER.
 DECF might signal ARITHMETIC-ERROR at runtime.

 DECODE-FLOAT should signal TYPE-ERROR if its argument is not type FLOAT.

 DENOMINATOR should signal TYPE-ERROR if its argument is not type RATIONAL.

 DEPOSIT-FIELD should signal TYPE-ERROR if its first argument is not type
	       INTEGER.
 DEPOSIT-FIELD might signal TYPE-ERROR if its second argument is not a
	       bytespec (something returned by BYTE). Note that byte
	       specifiers are not required to be disjoint from other types,
	       so this error checking is only heuristic.
 DEPOSIT-FIELD should signal TYPE-ERROR if its third argument is not type
	       INTEGER.

 DPB should signal TYPE-ERROR if its first argument is not type INTEGER.
 DPB might signal TYPE-ERROR if its second argument is not a bytespec
     (something returned by BYTE). Note that byte specifiers are not
     required to be disjoint from other types, so this error checking
     is only heuristic.
 DPB should signal TYPE-ERROR if its third argument is not type INTEGER.

 EVENP should signal TYPE-ERROR if its argument is not type INTEGER.

 FCEILING should signal TYPE-ERROR if its first argument is not type
	  (AND NUMBER (NOT COMPLEX)).
 FCEILING should signal TYPE-ERROR if its second argument is supplied
	  but is not type (AND NUMBER (NOT COMPLEX)).
 FCEILING should signal DIVISION-BY-ZERO if its second argument is
	  supplied and is zero.
 FCEILING might signal ARITHMETIC-ERROR.

 FFLOOR should signal TYPE-ERROR if its first argument is not type
	(AND NUMBER (NOT COMPLEX)).
 FFLOOR should signal TYPE-ERROR if its second argument is supplied
	but is not type (AND NUMBER (NOT COMPLEX)).
 FFLOOR should signal DIVISION-BY-ZERO if its second argument is
	supplied and is zero.
 FFLOOR might signal ARITHMETIC-ERROR.

 FLOOR should signal TYPE-ERROR if its first argument is not type
       (AND NUMBER (NOT COMPLEX)).
 FLOOR should signal TYPE-ERROR if its second argument is supplied
       but is not type (AND NUMBER (NOT COMPLEX)).
 FLOOR should signal DIVISION-BY-ZERO if its second argument is
       supplied and is zero.
 FLOOR might signal ARITHMETIC-ERROR.

 FROUND should signal TYPE-ERROR if its first argument is not type
	(AND NUMBER (NOT COMPLEX)).
 FROUND should signal TYPE-ERROR if its second argument is supplied
	but is not type (AND NUMBER (NOT COMPLEX)).
 FROUND should signal DIVISION-BY-ZERO if its second argument is
	supplied and is zero.
 FROUND might signal ARITHMETIC-ERROR.

 FTRUNCATE should signal TYPE-ERROR if its first argument is not type
	   (AND NUMBER (NOT COMPLEX)).
 FTRUNCATE should signal TYPE-ERROR if its second argument is supplied
	   but is not type (AND NUMBER (NOT COMPLEX)).
 FTRUNCATE should signal DIVISION-BY-ZERO if its second argument is
	   supplied and is zero.
 FTRUNCATE might signal ARITHMETIC-ERROR.

 GCD should signal TYPE-ERROR if any argument is not type INTEGER.
 GCD might signal ARITHMETIC-ERROR.

 EXP should signal TYPE-ERROR if its argument is not type NUMBER.
 EXP might signal ARITHMETIC-ERROR.

 EXPT should signal TYPE-ERROR if either argument is not type NUMBER.
 EXPT might signal ARITHMETIC-ERROR. e.g., (EXPT 0 0.0)

 FLOAT should signal TYPE-ERROR if its first argument is not type
       (AND NUMBER (NOT COMPLEX)).
 FLOAT should signal TYPE-ERROR if its second argument is supplied
       but is not type FLOAT.
 FLOAT might signal ARITHMETIC-ERROR.

 FLOAT-DIGITS should signal TYPE-ERROR if its argument is not type FLOAT.

 FLOAT-PRECISION should signal TYPE-ERROR if its argument is not type FLOAT.

 FLOAT-RADIX should signal TYPE-ERROR if its argument is not type FLOAT.

 FLOAT-SIGN should signal TYPE-ERROR if its first argument is not type
	    FLOAT.
 FLOAT-SIGN should signal TYPE-ERROR if its second argument is supplied
	    but is not type FLOAT.

 INCF might signal SYNTAX-ERROR at semantic processing time.
 INCF should signal TYPE-ERROR at runtime if the variable to be
      incremented does not have a value of type NUMBER.
 INCF might signal ARITHMETIC-ERROR at runtime.

 INTEGER-DECODE-FLOAT should signal TYPE-ERROR if its argument is not
		      type FLOAT.

 INTEGER-LENGTH should signal TYPE-ERROR if its argument is not type INTEGER.

 IMAGPART should signal TYPE-ERROR if its argument is not type NUMBER.

 ISQRT should signal TYPE-ERROR if its argument is not type (INTEGER 0).
 ISQRT might signal ARITHMETIC-ERROR.

 LCM should signal TYPE-ERROR if any argument is not type INTEGER.
 LCM might signal ARITHMETIC-ERROR.

 LDB might signal TYPE-ERROR if its first argument is not a bytespec
     (something returned by BYTE). Note that byte specifiers are not
     required to be disjoint from other types, so this error checking
     is only heuristic.
 LDB should signal TYPE-ERROR if its second argument is not type INTEGER.

 LDB-TEST might signal TYPE-ERROR if its first argument is not a bytespec
	  (something returned by BYTE). Note that byte specifiers are not
	  required to be disjoint from other types, so this error checking
	  is only heuristic.
 LDB-TEST should signal TYPE-ERROR if its second argument is not type INTEGER.

 LOG should signal TYPE-ERROR if either argument is not type NUMBER.
 LOG might signal ARITHMETIC-ERROR.

 LOGAND should signal TYPE-ERROR if any argument is not type INTEGER.

 LOGANDC1 should signal TYPE-ERROR if either argument is not type INTEGER.

 LOGANDC2 should signal TYPE-ERROR if either argument is not type INTEGER.

 LOGBITP should signal TYPE-ERROR if its first argument is not type
	 (INTEGER 0).
 LOGBITP should signal TYPE-ERROR if its second argument is not type
	 INTEGER.

 LOGCOUNT should signal TYPE-ERROR error if its argument is not type INTEGER.

 LOGEQV should signal TYPE-ERROR if any argument is not type INTEGER.

 LOGIOR should signal TYPE-ERROR if any argument is not type INTEGER.

 LOGNAND should signal TYPE-ERROR if either argument is not type INTEGER.

 LOGNOR should signal TYPE-ERROR if either argument is not type INTEGER.

 LOGNOT should signal TYPE-ERROR error if its argument is not type INTEGER.

 LOGORC1 should signal TYPE-ERROR if either argument is not type INTEGER.

 LOGORC2 should signal TYPE-ERROR if either argument is not type INTEGER.

 LOGTEST should signal TYPE-ERROR if either argument is not type INTEGER.

 LOGXOR should signal TYPE-ERROR if any argument is not type INTEGER.

 MAKE-RANDOM-STATE should signal TYPE-ERROR if an argument is supplied 
		   but is not type (OR (MEMBER NIL T) RANDOM-STATE).

 MASK-FIELD might signal TYPE-ERROR if its first argument is not a bytespec
	    (something returned by BYTE). Note that byte specifiers are not
	    required to be disjoint from other types, so this error checking
	    is only heuristic.
 MASK-FIELD should signal TYPE-ERROR if its second argument is not type
	    INTEGER.

 MAX should signal TYPE-ERROR if any argument is not type
     (AND NUMBERP (NOT COMPLEX)).
 MAX might signal ARITHMETIC-ERROR.

 MIN should signal TYPE-ERROR if any argument is not type
     (AND NUMBERP (NOT COMPLEX)).
 MIN might signal ARITHMETIC-ERROR.

 MINUSP should signal TYPE-ERROR if its argument is not type
	(AND NUMBER (NOT COMPLEX)).

 MOD should signal TYPE-ERROR if its first argument is not type
     (AND NUMBER (NOT COMPLEX)).
 MOD should signal TYPE-ERROR if its second argument is supplied
     but is not type (AND NUMBER (NOT COMPLEX)).
 MOD should signal DIVISION-BY-ZERO if its second argument is
     supplied and is zero.
 MOD might signal ARITHMETIC-ERROR.

 NUMERATOR should signal TYPE-ERROR if its argument is not type RATIONAL.

 ODDP should signal TYPE-ERROR if its argument is not type INTEGER.

 PHASE should signal TYPE-ERROR if its argument is not type NUMBER.
 PHASE might signal ARITHMETIC-ERROR.

 PLUSP should signal TYPE-ERROR if its argument is not type
       (AND NUMBER (NOT COMPLEX)).

 RANDOM should signal TYPE-ERROR if its first argument is not
	type (INTEGER 1).
 RANDOM should signal TYPE-ERROR if its second argument is supplied
	but is not type RANDOM-STATE.

 RANDOM-STATE-P will never signal an error.

 RATIONAL should signal TYPE-ERROR if its argument is not type
	  (AND NUMBER (NOT COMPLEX)).
 RATIONAL might signal ARITHMETIC-ERROR.

 RATIONALIZE should signal TYPE-ERROR if its argument is not type
	     (AND NUMBER (NOT COMPLEX)).
 RATIONALIZE might signal ARITHMETIC-ERROR.

 REALPART should signal TYPE-ERROR if its argument is not type NUMBER.

 REM should signal TYPE-ERROR if its first argument is not type
     (AND NUMBER (NOT COMPLEX)).
 REM should signal TYPE-ERROR if its second argument is supplied
     but is not type (AND NUMBER (NOT COMPLEX)).
 REM should signal DIVISION-BY-ZERO if its second argument is
     supplied and is zero.
 REM might signal ARITHMETIC-ERROR.

 ROUND should signal TYPE-ERROR if its first argument is not type
       (AND NUMBER (NOT COMPLEX)).
 ROUND should signal TYPE-ERROR if its second argument is supplied
       but is not type (AND NUMBER (NOT COMPLEX)).
 ROUND should signal DIVISION-BY-ZERO if its second argument is
       supplied and is zero.
 ROUND might signal ARITHMETIC-ERROR.

 SCALE-FLOAT should signal TYPE-ERROR if its first argument is not
	     type FLOAT.
 SCALE-FLOAT should signal TYPE-ERROR if its second argument is not
	     type INTEGER.

 SIGNUM should signal TYPE-ERROR if its argument is not type NUMBER.

 SIN should signal TYPE-ERROR if its argument is not type NUMBER.
 SIN might signal ARITHMETIC-ERROR.

 SINH should signal TYPE-ERROR if its argument is not type NUMBER.
 SINH might signal ARITHMETIC-ERROR.

 SQRT should signal TYPE-ERROR if its argument is not type NUMBER.
 SQRT might signal ARITHMETIC-ERROR.

 TAN should signal TYPE-ERROR if its argument is not type NUMBER.
 TAN might signal ARITHMETIC-ERROR.

 TANH should signal TYPE-ERROR if its argument is not type NUMBER.
 TANH might signal ARITHMETIC-ERROR.

 TRUNCATE should signal TYPE-ERROR if its first argument is not type
	  (AND NUMBER (NOT COMPLEX)).
 TRUNCATE should signal TYPE-ERROR if its second argument is supplied
	  but is not type (AND NUMBER (NOT COMPLEX)).
 TRUNCATE should signal DIVISION-BY-ZERO if its second argument is
	  supplied and is zero.
 TRUNCATE might signal ARITHMETIC-ERROR.

 ZEROP should signal TYPE-ERROR if its argument is not type NUMBER.

 * should signal TYPE-ERROR if any argument is not type NUMBER.
 * might signal ARITHMETIC-ERROR.

 + should signal TYPE-ERROR if any argument is not type NUMBER.
 + should signal TYPE-ERROR if any argument is not type NUMBER.
 + might signal ARITHMETIC-ERROR.

 - should signal TYPE-ERROR if any argument is not type NUMBER.
 - might signal ARITHMETIC-ERROR.

 / should signal TYPE-ERROR if any argument is not type NUMBER.
 / should signal DIVISION-BY-ZERO if any divisor argument is zero.
 / might signal ARITHMETIC-ERROR.

 /= should signal type-error if any argument is not type NUMBER.
 /= might signal ARITHMETIC-ERROR.

 1+ should signal TYPE-ERROR if any argument is not type NUMBER.
 1+ might signal ARITHMETIC-ERROR.

 1- should signal TYPE-ERROR if any argument is not type NUMBER.
 1- might signal ARITHMETIC-ERROR.

 < should signal TYPE-ERROR if any argument is not type
   (AND NUMBER (NOT COMPLEX)).
 < might signal ARITHMETIC-ERROR.

 <= should signal TYPE-ERROR if any argument is not type
    (AND NUMBER (NOT COMPLEX)).
 <= might signal ARITHMETIC-ERROR.

 = should signal TYPE-ERROR if any argument is not type NUMBER.
 = might signal ARITHMETIC-ERROR.

 > should signal TYPE-ERROR if any argument is not type
   (AND NUMBER (NOT COMPLEX)).
 > might signal ARITHMETIC-ERROR.

 >= should signal TYPE-ERROR if any argument is not type
    (AND NUMBER (NOT COMPLEX)).
 >= might signal ARITHMETIC-ERROR.

Rationale:

  This addresses the development and delivery concerns mentioned in the
  Problem Description.

Current Practice:

  Most implementations probably do not reliably signal the indicated
  errors in safe code.

Cost to Implementors:

  In implementations not providing the indicated error checking,
  considerable work might need to be done.

  The alternative is to identify the implementation as an "unsafe" subset.
  However, while it is a "subset" in the sense that code that was developed
  in it will run in the superset, it is important to understand that such
  implementations are not simply "places you can run code that's been
  thoroughly debugged in the full language" since such debugged code may
  still depend on the reliable detection and handling of certain kinds of
  errors.

Cost to Users:

  Technically none. These are supposedly already all `is an error'
  cases that people can't depend on.

  Some users might be relying on an implementation not to signal a particular
  error in compiled code.  Such code is already not portable, however.

  In some cases, where an implementation adds error checking that they
  consider unnecessary, the user will need to add some OPTIMIZE proclamations.

  Some users will see this as a bug fix.

Cost of Non-Adoption:

  The error handling facilities will be a lot less useful.
  Code that uses error handling will not port well.

Benefits:

  Better development environments. More robust delivered applications.

Aesthetics:

  Hopefully improved.

Discussion:

  Pitman getting this level of detail is a good idea. He's ammenable to
  specific changes if they improve the overall level of receptiveness to
  the proposal.

  Notes about how to proceed on this issue
  (to be removed prior to final vote):

  - Is anyone uncomfortable about the name ARITHMETIC-ERROR?
    If so, can someone mathematically inclined suggest a better name?
    `MATH-ERROR' or `NUMBER-ERROR' come to mind.

  - In some of the cases of "might signal", it might be the case that
    no signal should ever occur. Someone who's actually implemented these
    functions might want to suggest that in some cases we can remove
    this verbiage, or give examples of the circumstances under which the
    condition might be signalled?