[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
early error detection
Type checking also acts as a way to trap certain classes of errors early,
e.g. trying to do arithmetic on character strings. This operation
might never be detected and could simply provide wrong results to a computation
on stock hardware. This feature strikes me as being entirely analogous
to parity on memories; it lets you know AT THE EARLIEST MOMENT that something
has gone wrong.
This early-catching of errors is why I think the traditional approach to
slow type-checking (providing a compilation mode that turns it off) is
a mistake; it is precisely when your program is supposedly in production
that you most need to know that it has encountered such a bug. Even if you
handle the error with a trap handler and continue running, at least you have
the ability to know that it happened, rather than just blithely ignoring it.
This sounds good -- I wish symbolics took it even more seriously!
Look at the examples below.
(defstruct my-class (my-field 0 :type integer))
(+ 5 (my-class-my-field (make-my-class :my-field 'foo)))
==> error -- the second argument to +, FOO, was not a number
This is not THE EARLIEST MOMENT something went wrong -- the error occured
when I tried to stick a SYMBOL in a field that is supposed to hold
INTEGERs only. Your implementation is certainly allowable under the
common lisp spec, but I don't see how you can say you tried to catch
that error early. This error could have been detected when the
my-class instance was created, or even when the
(make-my-class :my-field 'foo) source code was translated!
We continue:
(defstruct my-other-class (my-other-field 20 :type integer))
(my-class-my-field (make-my-other-class))
==> 20.
NO ERROR SIGNALLED AT ALL. I have applied the operation my-class-my-field
to an operand of the wrong type (a my-other-class rather than a my-class).
And since the result turned out to be of the same type (integer)that would
have resulted had the operand been legal, it may be a long time, if
ever, before I really get an error. Maybe I'll just get incorrect
results, or my shuttle will crash.
It appears to me that you are serious about catching as many errors as
possible in hardware (which is fine) and not serious at all about
catching the others. I contend that most of my errors that are currently
caught by the hardware could be caught even earlier if the compiler
inserted the obvious checks. Personally, I would MUCH prefer having
compiler modes that let me develop code with all that extra checking
being performed, than having my develop and production modes be
identical, both catching ONLY the very limited set of type errors your tagged
hardware detects.
In summary, Common Lisp (even before CLOS) has provided a rich language of
TYPEs that extends type correctness beyond that of a small number of
primitive types (for which you have tag bits) and primitive operations
(for which your hardware checks those bits). Programmer defined operations
deal with both those types and, more commonly, programmer defined types.
Compile-time (where possible) and run-time (where not) detection of violatons
of these typed interfaces is a big win for a developer, just like catching
"illegal second argument to +" or "too many parameters passed to FOO".