[comp.lang.misc] Enumeration types and compiler size

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