Subject: Re: Big Numbers From: Erik Naggum <erik@naggum.net> Date: Sat, 20 Oct 2001 21:18:01 GMT Newsgroups: comp.lang.lisp Message-ID: <3212601477682467@naggum.net> * Dieter Menszner | The [Ada] Software I had to maintain e.g. produced constaint errors | whenever the incoming data didn't fit into the datatypes. Which is not | completely wrong. But the exeception handler routines didn't know how | to deal with the situation and just terminated the program. It suddenly dawned on me that this illustrates that the static typing people have yet to figure out what input to programs is all about. Neither user nor program input is statically typed. Look at all the messy coding you have to engage in to "convert" user input to the _expected_ type in most languages, and how the most convenient way of dealing with these things is to default to _strings_ that are converted on demand to the expected type for the expression in which they are used. A major "feature" of several languages is precisely that they achieve "dynamic types" through string representation and type conversions. The same goes for that XML abomination, which is barely able to express the "structure" of the input, but not any typed values other than "string". Several database interfaces also choose "string" as their "dynamic type" representation. Now, you may be able to control types statically in carefully controlled environments. Source code and compilation in a system environment that will never, ever change (it is instead _replaced_ in toto) is perhaps such a case. Everything else, _every_ input source to a program, is a source of problems (if you pardon the pun). This is why it is wrong for integers parsed from an input source to be limited in size by hardware. This is why it is wrong for a program to make its expectations explicit before it knows what it is dealing with. This is why Common Lisp's read is the right interface to deal with user input: It returns objects read from the character stream input source, parsed according to their _own_ inherent syntactic structure. The standard read function is too weak to deal with all it needs to deal with to be usable beyond the expectation to receive Common Lisp objects as input, but that is an implementation restriction that can be lifted, not an issue with the interface as such. How humans deal with the unexpected defines an important part of their personality. Some cannot deal with the unexpected at all, and work very hard to force the world into being what they expect it to be. This can go really bad when they try to force people to be what they expect them to be, such as by treating people not as people, but as manifestations of one's expectations about them. It appears that few people are able to work like read does: Deal with whatever there is they are exposed to. Most of the friction on USENET can be condensed to a failure to deal with people on their own terms -- as witness, all the moralists who claim that others should behave some different way and all those who reject _every_ notion of being told how to behave, even if they are actually not told. The enormous number of security problems found in programs written in C, with its amazingly unintelligent fixed buffer size design, shows us that even people one would expect (!) to be able to remember that buffer overruns is _the_ major cause of problems, still cannot bring themselves to write code without using that horribly broken design paradigm because they are so heavily influenced and consequently fooled by static typing. One might argue that static typing is not necessarily synonymous with disjoint hardware-oriented types, but the main reason people want static typing is the perceived ability to produce more efficient machine code from having the programmer to over-specify type information. This also means that the value of a type specification is lost if it is a general type like "integer" instead of a specific number of bits, such as would be the case if the language supported arbitrarily wide integers. Since there is so little value to these people in using any type in the type hierarchy above the hardware-supported types, this naturally leads to preferring _disjoint_ types, indeed _only_ supporting disjoint types. This is probably a good idea within a very restricted domain, that in which all "possible" values can be known a priori. A priori knowledge has great appeal to some people, but they seem to get flustered when facing the unknown, the uncertain, or the unexpected. This observation leads me to believe that those who want static typing want it for a far more important reason than ease of compiler design, neat type theories, and more efficient code: It presents an easy-to-understand universe with very few exceptional situations and where everything is somehow in order. Such is not the universe we live in, nor should we attempt to make the one we live in like that. In order to make input from the external world, which must be treated as unknowable a priori, work at all, the only way you can survive is to use some form of dynamic typing and types with no upper limit to precision. The way Common Lisp does this with its reader is still geared towards an expectation that it will receive Common Lisp input, but the core ideas of the syntax of Common Lisp are fundamentally _correct_: Objects identify their types syntactically, usually with a very low syntactic overhead, and the reader returns the appropriate type object after parsing it, potentially having dealt with any anomalies and errors in the input. I think the reader in the Common Lisp system is extremely under-utilized, probably because of the large number of "security problems" related to its current design and implementation, such as remembering to turn off *read-eval* and the inability to control the behavior of what would be interned as symbols. If it were better understood as the _right_ way to deal with user input (as opposed to _expecting_ certain kinds of input), it would be used more and would probably also have a much improved, but as long as people stick to the statically-typed _model_ of doing user input, they will both work too hard on it getting worse results and their code will have to be modified ever time they make a small change to the syntax or the type system or their expectations. Notice how the Common Lisp _compiler_ is a lot more adaptible than that because it uses read to get the source code and objects into the internal form it can deal with. The same should _ideally_ apply to any Common Lisp application. /// -- Norway is now run by a priest from the fundamentalist Christian People's Party, the fifth largest party representing one eighth of the electorate. -- The purpose of computing is insight, not numbers. -- Richard Hamming