Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!security!genrad!decvax!yale-com!leichter From: leichter@yale-com.UUCP (Jerry Leichter) Newsgroups: net.lang Subject: Whats wrong with strong typing Message-ID: <2582@yale-com.UUCP> Date: Mon, 12-Dec-83 16:16:33 EST Article-I.D.: yale-com.2582 Posted: Mon Dec 12 16:16:33 1983 Date-Received: Wed, 14-Dec-83 01:37:53 EST References: kobold.214 Lines: 77 Strong typing as it is implemented has a couple of problems: a) It's an incomplete facility. Giving a variable a compiler-checked type is essentially an assertion about the values that variable will contain. Originally, in the grand-daddy of all typed languages (FORTRAN), the assertion was based on hardware limitations: I promise to put nothing but integers in this here variable, but I may put real numbers in that there variable. Some additional things got dragged along: The definition of division was different for different "types". Well, it's rarely of great interest to me that a variable is always an integer. PASCAL took a great leap forward in adding some typing information (ranges) that had not DIRECT correlation with hardware representation. In the process, however, it lost the ability to provide complete checks at compile time, and few PASCAL compilers check at run-time either. However, the original basis of type distinctions remains in PASCAL and many related languages: The compiler provides a small, essentially arbitrary set of assertions that it recognizes. Consider that, for a two's-complement machine, I can assert that the TOP bit is 0 (by an range assertion I >= 0), but not that the BOTTOM bit is 0 (I is even - something that might be very nice to be able to say if I is going to be used as a word address on an 11.) b) It requires me to tell the system things that it ought to be able to figure out for itself. If I is used ONLY as a loop counter, the compiler can easily tell that I can only take on integer values. Why should I have to say so? Let the compiler tell ME what it has decided it knows about each of the variables. In particular, let it tell me when it is unable to learn enough about a variable to generate good code (it can always insert run-time checks); then I can come back and provide such information as I have. People object to this approach on two grounds. The first is a religeous belief that "default declarations" are bad, because PL/I used them and we all know that NOTHING that PL/I did was right. The second is the belief that the source code of a program tell a human reader everything about it. I see no requirement for this at all. Let people read compiler listings, which the compiler will then carefully annotate with the "missing" information. With proper design, the annotated compiler output could be use as INPUT to a later compilation; you would just discard the original source and replace it with the improved version. We already do this with pretty-printers for the sake of simple syntactic clean-up; there is no reason not to do it for "semantic cleanup". Finally, my own personal experience, in about 16 years of programming, both in academia and industry, including a large amount of teaching of programming and grading student programs, in a large variety of languages, is that the\ "problem" being solved by most strong-typing systems - compile-time checking for inconsistencies - is just NOT a significant problem in real life. in my own code, I can think of ONE case where a type-confusion caused in problem (in SNOBOL, and in a context that could not even be expressed in a language without dynamic typing). Problems I do find are more subtle and often have to do with order and meaning of arguments to functions that take many argu- ments - but usually there are multiple arguments of the same type so a typing system wouldn't catch them anyway. A more general assertional system MIGHT - and would be an extraordinarily useful thing anyway, much more useful than any static typing system I've ever seen. Consider the interesting question of whether recursive functions should be declared "recursive". At one time, there were arguments for this: After all, a function that is NOT recursive can be executed more efficiently on many architectures (especially old ones) since it can use a static context frame. Besides, on general "strong typing" arguments, I should be warning the reader - and the compiler - about an important fact about my function. "Recursive" declarations have pretty much disappeared. Hardware stack support was a contributer, but there was also the theoretical argument - which I believe I once saw made by Dijkstra - that if a recursive declaration were to be allowed, it should be checked. But the only way to check if that a function is or is not recursive is to compute the transitive closure of the call graph - easy in "standard" PASCAL, with not external functions, for example - from which one could as easily have the compiler decide for itself that the function is or is not recursive. Hence, the declaration is redundant. My claim is that the same reasoning ought to be applied to other type information. -- Jerry decvax!yale-comix!leichter leichter@yale