sommar@enea.se (Erland Sommarskog) (01/13/91)
Also sprach Marc Brandis (brandis@inf.ethz.ch): >I said: >>As I recall Wirth's paper, the reason he gave for removing >>enumerates was that he wanted to keep down compiler in size. > >This is certainly wrong, and the evidence that Richard Bielak found is >correct. Let me cite what Wirth said in "From Modula to Oberon". I stand by my word. Wirth talks a little in circles and gives some half-hearted excuses at first, and then concludes with some not far from what I said: > This exceptional rule defies conceptual simplicity and > causes unpleasant problems for the implementor. >When you look at where enumerations are used in programs, you will notice that >in a extensible software environment like Oberon, you definitely want to be >able to extend these constructs. You can easily do this when using INTEGERS >together with constants (just define some additional constants), but it is not >that easy when having enumerations in the language. Like in one module I have: CONST Red = 1; Blue = 2; Green = 3; Yellow = 4; and in another I extend this "type" with CONST Black = 5; White = 6; Now, back in the original module I realize I need Orange too and add Orange = 5; to the list. Either I remember to change the values for black and white, or I don't. Easy? For the compiler writer, sure. For me? Error prone and difficulties just becuase someone was lazy when he defined the language. A similar problem is the following: TYPE Colours = (Red, Green, Blue); Fruits = (Apple, Orange, Pear); VAR C : Colour; F : Fruit; BEGIN ... C := F; In Pascal and Modula this won't compile beacuse of the type conflict. But in Ob(solet)eron we would have CONST Red = 1; Green = 2; Blue = 3; Apple = 1; Orange = 2; Pear = 3; TYPE Colours = integer; Fruits = integer; VAR C : Colour; F : Fruit; BEGIN ... C := F; which, unless the typing rules are different to Pascal, compiles just fine, but isn't correct for five seconds. >Now, what would the value of an >instance of an extended type seen as the base type? E.g. > > TYPE > Colors = (red, green, blue); > MoreColors = (Colors)(yellow); > >Now assume that you have an instance of MoreColors with the value yellow. What >is now the value of this variable when seen as a Colors? Assume that you have an uninitialized instance of Colours with the numeric value 62. What value does it have? Answer: out of range. >To your statement about smaller and simpler compilers, and Wirth's obsession, >I have to add something. First, as you may have found yourself: smaller and >simpler programs are easier to maintain and to write and contain less bugs! And are usually less useful. >Wirth's idea is to weight cost against win, as every good engineer should do. >I think that it is time for the software industry to recognize that programs >do not become better by adding tons of features. In this case this is just ludicrous. Sure, by keeping down the compiler size, you have less bugs in it. But by keeping down the language in expressive power you 1) increase the size of the programmer's program 2) gives him less possibilities to discover stupid bugs early. -- Erland Sommarskog - ENEA Data, Stockholm - sommar@enea.se "There is only one success -- to be able to spend your life in your own way" Christopher Morely
brandis@inf.ethz.ch (Marc Brandis) (01/15/91)
In article <2390@enea.se> sommar@enea.se (Erland Sommarskog) writes: >Also sprach Marc Brandis (brandis@inf.ethz.ch): >>I said: >>>As I recall Wirth's paper, the reason he gave for removing >>>enumerates was that he wanted to keep down compiler in size. >> >>This is certainly wrong, and the evidence that Richard Bielak found is >>correct. Let me cite what Wirth said in "From Modula to Oberon". > >I stand by my word. Wirth talks a little in circles and gives some >half-hearted excuses at first, and then concludes with some not >far from what I said: > >> This exceptional rule defies conceptual simplicity and >> causes unpleasant problems for the implementor. Why do you not leave the citation in the posting so that everybody can decide himself whether Wirth talks in circles and gives half-hearted excuses? I do not agree. Here is the citation again: Enumeration types appear to be a simple enough feature to be uncontroversial. However, they defy extensibility over module boundaries. Either a facility to extend given enumeration types has to be introduced, or they have to be dropped. A reason in favour of the latter, radical solution was the observation that in a growing number of programs the indiscriminate use of enumerations (and subranges) had led to a type explosion that contributed not to program clarity but rather to verbosity. In connection with import and export, enumerations give rise to the exceptional rule that the import of a type identifier also causes the (automatic) import of all associated constant identifiers. This exceptional rule defies conceptual simplicity and causes unpleasant problems for the implementor. This is not what you said. The important point is that the language (not the compiler) becomes more complicated from a conceptual (!) standpoint of view. Of course, dropping it makes it easier for the implementor too, and the compiler becomes smaller, but the reason to drop it was not to make the compiler smaller. I said: >>When you look at where enumerations are used in programs, you will notice that >>in a extensible software environment like Oberon, you definitely want to be >>able to extend these constructs. You can easily do this when using INTEGERS >>together with constants (just define some additional constants), but it is not >>that easy when having enumerations in the language. > >Like in one module I have: > > CONST Red = 1; Blue = 2; Green = 3; Yellow = 4; > >and in another I extend this "type" with > > CONST Black = 5; White = 6; > >Now, back in the original module I realize I need Orange too and >add Orange = 5; to the list. Either I remember to change the >values for black and white, or I don't. Easy? For the compiler >writer, sure. For me? Error prone and difficulties just becuase >someone was lazy when he defined the language. This is bad programming style. In an extensible software environment, you do not extend a module by changing the source of it but by writing an extension in another module. So, after you had finished the module containing the base type, and then writing extensions of it in another module, you should not go back to the base module and change it, so the case where you notice that you need Orange will not occur. The only reason to go back to the base module is to do bug fixes, but there you should not be required to extend the range of values. Another reason why you should change a base module only for bug fixes: The interface of a module does not define the semantics of the module. So, if you change the semantics of the base module, you may invalidate everything relying on it. Anyway, you can make this code better by defining the maximum value of the basetype (ColorMax = Yellow) and then making the extensions relative to it, that is Black = Base.ColorMax+1; White = Black+1; >A similar problem is the following: > > TYPE Colours = (Red, Green, Blue); > Fruits = (Apple, Orange, Pear); > VAR C : Colour; > F : Fruit; > BEGIN > ... > C := F; > >In Pascal and Modula this won't compile beacuse of the type conflict. >But in Ob(solet)eron we would have > > CONST Red = 1; Green = 2; Blue = 3; > Apple = 1; Orange = 2; Pear = 3; > TYPE Colours = integer; > Fruits = integer; > VAR C : Colour; > F : Fruit; > BEGIN > ... > C := F; > >which, unless the typing rules are different to Pascal, compiles just >fine, but isn't correct for five seconds. This compiles just fine under Oberon. However, if you would have used meaningfull names for your variables, this would not have occured. I agree that this may sometimes cause problems in the context of parameter passing, but a language cannot catch every error that a programmer may make. Experience of the community of Oberon programmers shows that this error occurs seldom enough not to introduce new constructs into the language. I said: >>Now, what would the value of an >>instance of an extended type seen as the base type? E.g. >> >> TYPE >> Colors = (red, green, blue); >> MoreColors = (Colors)(yellow); >> >>Now assume that you have an instance of MoreColors with the value yellow. What >>is now the value of this variable when seen as a Colors? > >Assume that you have an uninitialized instance of Colours with the numeric >value 62. What value does it have? Answer: out of range. This is not the same case. If a value is out of range, you should get an overflow trap. But it is correct to assign the instance of an extended type to an instance of the base type. This is what extensibility is all about. If you do not allow this, you defy extensibility (as Wirth said), making the construct useless in a extensible software environment. I said: >>To your statement about smaller and simpler compilers, and Wirth's obsession, >>I have to add something. First, as you may have found yourself: smaller and >>simpler programs are easier to maintain and to write and contain less bugs! > >And are usually less useful. > This is just not true. If you have the right functions and can use them in any context, you get a lot of functionality by combining them. This is a much better approach than having a feature-loaden program which copes with every case especially. Most of the time, some cases have been forgotten or been implemented wrong. This was for example one reason why UNIX was so successful: a set of small simple tools that could be combined to do something more complex. I said: >>Wirth's idea is to weight cost against win, as every good engineer should do. >>I think that it is time for the software industry to recognize that programs >>do not become better by adding tons of features. > >In this case this is just ludicrous. Sure, by keeping down the >compiler size, you have less bugs in it. But by keeping down the >language in expressive power you 1) increase the size of the >programmer's program 2) gives him less possibilities to discover >stupid bugs early. The expressive power of Oberon without enumeration types is not smaller than its expressive power with enumeration types. The programs do not get larger. In fact, Oberon programs are much smaller than programs written in other languages (this is something I cannot prove here, but it is evidence from my daily use of both Oberon and UNIX and C). The stupid errors described above occur seldom enough not to defy conceptual simplicity of the language. However, if a conceptually (!) simple concept for extensible enumeration types can be found, its inclusion into a language like Oberon should be reconsidered. Marc-Michael Brandis Computer Systems Laboratory, ETH-Zentrum (Swiss Federal Institute of Technology) CH-8092 Zurich, Switzerland email: brandis@inf.ethz.ch