Cleanup Issue ERROR-CHECKING-IN-NUMBERS-CHAPTER

Status
For Internal Discussion
Forum
Cleanup
Category
CHANGE
References
Numbers (pp193-232), S:>kmp>cl>conditions>revision-18-notes.text.34 (formerly S:>kmp>cl-conditions.text.34),

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 (SCARECROW)

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. + 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?

Edit History