Path: utzoo!censor!geac!torsqnt!lethe!yunexus!ists!helios.physics.utoronto.ca!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!lll-winken!elroy.jpl.nasa.gov!decwrl!pa.dec.com!rust.zso.dec.com!shlump.nac.dec.com!engage!marx.enet.dec.com!grier From: grier@marx.enet.dec.com Newsgroups: comp.lang.misc Subject: Re: Runtime Polymorphism -- To Have and Have Not (Par Message-ID: <1991Mar2.002608.20387@engage.enet.dec.com> Date: 2 Mar 91 00:26:08 GMT References: <559@coatimundi.cs.arizona.edu> Sender: news@engage.enet.dec.com (USENET News System) Reply-To: grier@marx.enet.dec.com () Organization: Digital Equipment Corporation Lines: 183 In article <559@coatimundi.cs.arizona.edu>, gudeman@cs.arizona.edu (David Gudeman) writes: |> Runtime polymorphism (or runtime typing, or dynamic typing) means that |> identifiers in a language do not have types that are fixed at compile |> time, they can reference values of different types at different times |> in the program. Languages with runtime polymorphism include Lisp, |> Smalltalk, Icon, and Prolog. Not necessarily, if you accept that there's a difference between "type" and "class". In most models I've seen, variables have a type, and instances have a class. The type of the variable limits the class of the instances which can be represented by that variable. At least in the object-oriented space, which seems to be what you're talking about. (Note that sometimes people invert the meaning of type and class as I've presented it above. This is the way I've seen it and worked with it, so it's the way I talk about it. Let's not war over the terms...) Some languages, Trellis, for instance, allow the programmer to narrow the type of a variable during a particular scope. I believe the Trellis syntax is something like: s : Shape; type_case s of Circle :begin ... end; Square : begin ... end; end; Within the blocks, the compiler (and thus the type system) knew that the type of "s" had been narrowed to include only Circle and subclasses or Square and subclasses. (the only problem here is that if you follow the common notion that classes partition instances, and the tags on the case-arms are types, there can be ambiguity, for instance: s : Object; -- root of the hierarchy presumably type_case s of sortable :begin ... end; number :begin ... end; end; In practice however, the types chosen will partition the hierarchy, and some simple rule such as "take the first type-case branch which matches" can be applied successfully.) This feature isn't necessarily particular to OO languages and systems either, I believe Trellis inherited the concept from CLU which had something similar in relation to its REFANY type. |> |> There are several advantages to this... Your comments seem to apply more to weakly typed systems rather than systems which include polymorphism and late binding. Is this perhaps what you meant? |> |> Another advantage of runtime polymorphism is code generality... |> This has little to do with runtime polymorphism. Ada generics, CLU and Trellis type generators and C++ templates all provide for generation of generic modules of code. Of the three, only Trellis has late binding. (It's coming back to me... CLU has the REFANY type, but the CLU equivalent of type_case has to be applied to it to a particular type before applying any operations except assignment to it...) |> |> There are two problems with runtime typing (or I should say, one |> problem and one complaint of questionable importance) First, it is |> very hard to make these programs run fast. In practice, most programs |> use most variables in a type-consistent way, but the user pays the |> performance penalty of having runtime type checks everywhere. These |> type checks can be largely eliminated by type inference, but not |> entirely. And there still must be some mechanism for cleanly |> combining values of unknown type with values of known type. With respect to polymorphism and late binding, wrong. A good compiler with strong typing and enough information can generate code which is just as good. Largely, it needs the ability to perform some broader analysis of the type system of the program than is typically available in languages/compilers where your code jumps from being a source form into an object which can be munged by the link-editor into an executable program. DEC's Ada compiler, for instance, is able to perform inter-module inlining quite well because of its use of a program library - something which a language like C++ has to resort to making the programmer put detailed implementation information in the public definition in order to gain some efficiency. Trellis also has the same characteristic, since it owns the workspace/program library in which the code is compiled and executed. (C++ could fix this if the language definition wasn't so slanted towards a specific technique to implement the language structures. As it stands, such analysis could probably only be performed by "smart" link-editors, which while they might be smart enough to do some inlining, certainly can't be smart enough to see the larger patterns of usage which might better drive decisions around inlining and genericity.) Even in weakly-typed languages, a lot can be done here. See some recent postings to comp.arch from an author who had a compiler which performed a large amount of optimization and inlining (is that a word?) on a weakly typed language. |> The questionable complaint about runtime typing is that it leads to |> hard-to-find errors that are not caught until runtime. It is true |> that type errors in such languages cannot be found until runtime, and |> that the place where a runtime error actually occurs is not always |> near where the error originated. On rare occasions these errors |> require some serious debugging. But in my experience this is a minor |> problem, and the time spent looking for these errors is quite small |> compared to the time that would have been spent writing strongly typed |> declarations. Aha! We are talking about weak typing vs. strong typing! What's your goal here? Research or engineering? If you're researching some idea, or even prototyping a product, I agree with you - the main factor has to be eliminating any overhead for development so that the idea can be turned into something which runs. If you're engineering a product which you're planning on selling to people which they're going to use to run their business, adjust control surfaces on a plane or monitor a nuclear power-plant, I strongly disagree with you. The cost of long-term maintenance of software far outweighs and exceeds the initial development cost, and warrants additional discipline during the development phase. Not to mention that even if you don't hold a legal responsilbity for damages incurred, you hopefully hold some moral responsibility. Sorry, this kind of stuff belongs in comp.software-eng... Neither philosophy is good in isolation however. If it's a major research project which might last several years and reach a size of some hundreds of thousands of lines of code, the cost of applying good engineering principles up front will pay for themselves in being able to advance the model with safety that either (a) clients of the code you're changing are adhering to documented exported interfaces and (b) if they don't, the compiler will catch it instead of letting it run for three days and then crash mysteriously. And there are times when performing Software Engineering (in the most pure form!) when you need to mung bits the way only a weak- typed language can. (However, most strongly typed languages have escapes to do this in a controlled fashion anyways.) (My opinion is that programming with a strongly typed language is a simple discipline which once you get used to it doesn't slow you down or hurt your ability to produce code at all. Sort of like getting in the habit of showering and brushing your teeth in the morning. If you don't do them, it probably seems like a hard thing to get used to, but if you can just discipline yourself long enough to get used to it, it's second nature and doesn't take any additional effort. And people don't put their hand over their nose when you're talking to them in close quarters! ;-) |> |> Even so, I believe that there is a solution to both of these problems |> that still leaves the advantages of runtime polymorphism intact. I'll |> discuss the solution in a later posting (and maybe answer some of the |> flames that this article may generate :-). No flames here! I just think that either you were using the wrong terminology, or hadn't realized that we have the technology to do these things right. |> -- |> David Gudeman |> gudeman@cs.arizona.edu |> noao!arizona!gudeman |> ------------------------------------------------------------------------ I'm saying this, not Digital. Don't hold them responsibile for it! Michael J. Grier Digital Equipment Corporation (508) 496-8417 grier@leno.dec.com Littleton, Mass, USA Mailstop OGO1-1/R6