Xref: utzoo comp.lang.misc:7330 comp.object:3085 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!ucsd!ucbvax!bloom-beacon!eru!hagbard!sunic!mcsun!hp4nl!charon!guido From: guido@cwi.nl (Guido van Rossum) Newsgroups: comp.lang.misc,comp.object Subject: Re: Run-time Type Errors in Smalltalk (was Re: blip (was...)) Message-ID: <3288@charon.cwi.nl> Date: 8 Apr 91 22:44:28 GMT References: <1991Apr8.085602.5082@tkou02.enet.dec.com> Sender: news@cwi.nl Followup-To: comp.lang.misc Lines: 115 Norman Diamond writes: >The multi-megabyte run time system would be useful while developing >programs in statically typed languages too, and then you'd never see >the mystery core dump. Debates between static and dynamic typing should >center on the advantages of programming in each kind of language, not >on what can be done with multi-megabyte support packages. Maybe I can provide something of a data point here: a comparison of two languages that differ more in their typing system than in other aspects. If you know ABC and Python you can skip to DISCUSSION at the end. Python, which has dynamic typing, was strongly inspired by ABC, which has static typing. In other aspects, the two are much more similar then your average pair of statically/dynamically typed languages: both are interactive and interpreted, and have large runtime packages that replace core dumps by understandable error messages (really exceptions for Python). Both runtime packages implement very-high level data types with roughly the same functionality (only one has bignums -- oddly enough it's the statically typed one). Neither requires or allows declarations, both have polymorphic functions. And now the differences: the type system of ABC determines the type of parameters and variables by inspecting how they are used -- e.g., if it is added to something, it must be a number (there's only one numeric type in ABC), if it is inserted in a list, it must have the same type as the elements of that list, etc. You get polymorphism if the usage of a parameter doesn't give away all the information about a type -- e.g., if a procedure swaps its two arguments but does nothing else, it will accept arguments of any type, as long as the two arguments have the same type. There are interesting problems when you try to write a type-checker for such a language, but they are solvable (for ABC, at least). Python, on the other hand, does all its type checking at run time. E.g., if you try to add two objects, their types are compared, and if they are both strings, or both integers, it succeeds, else you get a type checking exception (which may be caught). Programming in either language is extremely smooth compared to C or other relatively low-level languages. Because of the interpreters, you don't get blinding speed if you can't get the built-in data types to do most of the work for you, so neither language (implementation) is well-suited for programming byte-copying loops or FFT transforms, for example; but if you need efficient, large dynamic data structures, they are available in the runtime system. DISCUSSION There are two questions which can be asked about ABC and Python (in the context of the previous debate about static vs. dynamic typing). 1) Which is more likely to lead to bugfree programs? 2) Which has more flexibility (or: which do you like better)? Re (1), I don't see a significant difference. True, ABC detects certain errors before you start running the program that Python will only catch in a test run, but there remains a significant class of errors that can only be detected at run time, e.g., taking the MIN of an empty list, accessing an associative array with a non-existent key, etc. Both Python and ABC encourage program development in small units that are created and tested bottom-up, and the first test run usually finds any type errors that remain in Python programs. Sometimes the type checker in ABC detects a type error but reports it in such a weird way that you have to stare really long at the piece of code in question before you see what the real problem is; e.g., it may complain that b is not a number in a+b, while the real problem is in the expression assigned to b many lines earlier. In Python I can ask the debugger to print b's value when an exception has occurred, which usually shows immediately what the problem is (the value gives a more precise clue about where it came from than just the type, which ABC reports). Re (2), it can't be a surprise that I like Python better. I actually use heterogeneous lists a lot, e.g., just this weekend I wrote a tree module which stores arbitrary attributes associated with the leaves, keyed on strings chosen by the various modules that use the trees, and an event queue which can store arbitrary events from unrelated modules. These modules would pass ABC's type system alright (except for other features not provided in ABC that don't relate directly to dynamic/static typing), but their callers wouldn't: as soon as two unrelated modules would store differently-typed events in a queue, neither module would type-check. This is caused by the absence of unions in ABC, but notice that they would have to be open-ended unions (David Gudeman's "any" type), since the queue module cannot know what types will be stored in the queue. Any one program will only store a finite number of different event types (hmm, can you prove this?) but I don't see the point of forcing the programmer to find out which union type to use in a particular program (and keeping it up-to-date when the program is extended). CONCLUSION Were all else kept equal, I'd still prefer dynamic typing. Its simplicity in implementation wins over the complexity of a type checker that provides the kind of flexibility I need. ABC is close, but still too limiting for many realistic applications, and its type checker was one of the hardest modules to add to the system. Note that dynamically typed languages can often be optimized using techniques similar to ABC's type checking algorithm -- only they can fall back on the dynamic type system if they can't compute the type of a variable, instead of blaming the user. I would even like it if such an optimizer told me when it could prove that an unchecked exception would certainly occur in a part of the program. But there is no reason why such an optimizer should stop at type checking -- static checks can check for definedness of variables (ABC has this!), apply range checks, in short try to predict every kind of exception that may occur in a program -- but there is no reason to restrict the language to accept only programs for which it can be proven (with known techniques) that no exception will ever occur. Such languages are unnecessarily restricting programmers. --Guido van Rossum, CWI, Amsterdam "I can do everything you want in Macro Assembler. No need for Compilers."