Enumerations in Oberon (was: Re: Enumerated types) 
Author Message
 Enumerations in Oberon (was: Re: Enumerated types)

Quote:


>>Although I'm not sure exactly why, but enumeration type present some
>>difficult problems to the compiler when types are extended through
>>inheritance. My evidence? Look at OBERON, latest language from N.
>>Wirth, it does not have enumerated types.

>As I recall Wirth's paper, the reason he gave for removing
>enumerates was that he wanted to keep down compiler in size.
>A good reason? Obsession, if you ask me. (And I recall that
>enumeration types would not be a problem in Oberon. All you
>can extend is record types.

This is certainly wrong, and the evidence that Richard Bielak found is correct.
Let me cite what Wirth said in "From Modula to Oberon".

        Enumeration types appear to be a simple enough feature to be uncontro-
        versial. 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) has
        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.

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.

Note that when you have to do it with INTEGERS and constant, the semantics are
obvious. If you implement extensible enumeration types, they are not so
obvious. First, in Oberon, an instance of an extended type is always also an
instance of the base type. The value of this instance seen as the base type
is well-defined by the concept of projection. 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?

Another problem is how to implement type checks and type guards.

All these problems have been discussed, and there are solutions to all of them,
but it is not clear whether the advantages of having enumeration types out-
weights the conceptual complications on several fronts.

Last but not least, there is a big problem in the import of such enumerated
types. When you import an enumerated type, all its associated constants become
imported as well and are put into the outermost scope. If two modules use
the same constant name in an enumeration, and both modules are imported by
another module, you get a name conflict. Of course, you can solve the name
conflict by using type information from the context in which the constant is
used, but it is not easy to do.

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!
I am using several implementations of Oberon myself, and I have to say that
compiler bugs are found very (!!!) rarely. And there has never been something
like a list of known bugs, as every bug was so easy to fix that it could be
done in less than a day. (Do not flame me on this, I know that this is not
possible in a commercial environment. But I am convinced that bug-fixing in
these multiple-hundred-thousands of lines compilers is much harder than in
the less than 5000 lines Oberon compilers).

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 fact, when you browse
through journals like BYTE or PC Journal, you will see that many power users
(like Pournelle or Dvorak) would love to go back to some simple and small
programs that they used in their CP/M or early DOS time instead of having to
use the feature- and bug-loaded new programs, which are about an order of
magnitude slower on a machine that is an order of magnitude faster, compared
to their old programs.

The same is true for programming languages.

As this does not have too much to do with Eiffel, followups directed to
comp.lang.misc.

Marc-Michael Brandis
Computer Systems Laboratory, ETH-Zentrum (Swiss Federal Institute of Technology)
CH-8092 Zurich, Switzerland



Tue, 22 Jun 1993 16:40:02 GMT  
 Enumerations in Oberon (was: Re: Enumerated types)

Quote:
>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:

Quote:
>       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.

Quote:
>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.

Quote:
>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.

Quote:
>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.
--

"There is only one success -- to be able to spend your life in your own way"
Christopher Morely


Thu, 01 Jul 1993 04:36:33 GMT  
 Enumerations in Oberon (was: Re: Enumerated types)

Quote:


>>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:

Quote:
>>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;

- Show quoted text -

Quote:
>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:

Quote:
>>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:

Quote:
>>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:

Quote:
>>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



Sat, 03 Jul 1993 15:40:02 GMT  
 Enumerations in Oberon (was: Re: Enumerated types)

Quote:
>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?

In the interest of brevity. Your article was mentioned in the reference
header and interested readers could have gone back to it.

Quote:
> (Example of mine and explanations deleted.)

>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.

Apparently it is bad programming style in Oberon. The real world may
be different, though. You may always do the right design at first
shot, I do not. The net result of adding Orange, which should have
been in the base module from the very beginning, in a third module
is that we get one more module and unnecessary complexity added to
the later maintenance.

Quote:
>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.

So what? It might take a night to recompile, this may or may not be
a headache. If you take the decision to change the base module, it is
probably because you can live with it.

Quote:
>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;

Oh, so Oberon allow expressions for constant declarations. I didn't
know that, only that standard Pascal did not. Of course using a
thing like Base.ColourMax would be better. Just make sure you remember
to change it when you add a new colour in the base module.

Quote:
>> (My example of unwanted compatibility between integer enumerations deleted)
>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,

You got it. Parameter passing. I chose assignment for the example
since that easier to demonstrate, but the main problem is with
procedure calls. "Hm, in which order did the parameters come?"

Quote:
>but a language cannot catch every error that a programmer may make.

No, but this is an error it could, and should, catch. The later
you find an error, the more it will cost you.

Quote:
>Experience of the community of Oberon programmers shows that this
>error occurs seldom enough not to introduce new constructs into the
>language.

My experience of five years with various Pascal dialects is that
it does occur, and the risk that it may occur increases the number
of things you have to take in mind when you look for bugs. Also,
I have this impression that disallowing implicit assignment integer
types like Ada do, requires you be careful what you really are
mixing. "Hm, does apples and oranges really have anything to do
with each other?"
--

"There is only one success -- to be able to spend your life in your own way"
Christopher Morely


Fri, 09 Jul 1993 01:56:57 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. Using enumerated data types?

2. Problems with enumerated type and DataSocket

3. Enumerated Type Remove Item Potential Bug

4. "-" In enumerated data type

5. creating an enumerated type

6. creating an enumerated type

7. Why no enumerated types?

8. Lack of enumerated types.

9. Pseudo enumerated types

10. Enumerated Data Types in REXX

11. Q: Xlating text input to Enumerated Type

12. Enumerated typed in Scheme...???

 

 
Powered by phpBB® Forum Software