Enum matrix example

bearophile bearophileHUGS at lycos.com
Thu May 26 14:14:46 PDT 2011


Instead of writing articles about D (for the iPad contest too) I often prefer to write my notes in this newsgroup :-)

Comparisons with other languages are very useful. A little program I've composed to show some simple but interesting features of the Ada language (the Text_IO and Put_Line are not useful here). This Ada code does things that are useful or quite useful in a bit larger programs (related code is present in a larger program):


with Ada.Text_IO; use Ada.Text_IO;
procedure Prog is
  type ABC is ('A', 'B', 'C');
  type Table is array (Positive range <>, Positive range <>) of ABC;
  Board : Table := ("AAAAAAAA", "BBBBBBBB",
                    "CCCCCCCC");
begin
  Put_Line("");
end Prog;

------------------------

A first approximate translation to D2 (better translations are surely possible):

void main() {
    enum ABC : char { A='A', B='B', C='C' } // Issue 6057
    alias ABC[][] Table;
    // See issue 6059 too
    Table board = [cast(ABC[])"AAAAAAAA", cast(ABC[])"BBBBBBB",
                   cast(ABC[])"CCCCCCCC", cast(ABC[])"DDDDDDD"];
} // end main


------------------------

Some notes about the Ada code and its D equivalents:

In the Ada code I have given the name "Prog" to the main procedure. In D I have just used main().

Ada allows to optionally specify the name of the function, procedure or statement that is ending, so there is a "end Prog;" at the end. The compiler tests and enforces that such optional names are correct. This feature is handy when you later read the code, to know where you are. Nested functions and other nesting gets simpler to understand for the person that is reading the code, and the compiler makes sure that annotation is correct. If you don't like such annotations, you are free to not add them.

In D I usually add a comment at the closing braces, even with the risk of them getting out of sync:

} // end of foo()

------------------------

Inside the procedure Prog there is the definition of an enumerate type ABC of chars.
In issue 6057 I've shown that in D2 you have to put this enum definition outside the main().

------------------------

Then the Ada code defines the type Table, as a rectangular 2D stack-allocated fixed-sized array. The "range <>" means that the sizes of such 2D array are not specified in the type itself, so they are not known at compile-time, so they are dynamic. This is like the definition of the type of a generic 2D C99 Variable Length Array.

In D I have used:
alias ABC[][] Table;

This is far different:
- It's a dynamic array, so generally it's not stack-allocated.
- It is an alias, so it's not a strong type, so the compiler and function arguments are free to confuse it with another 2D array of ABC that has a totally different purpose and meaning in the program.
- And it's not rectangular. D offers no native way to ask for a rectangular array when the array sizes are unknown at compile time. This forces me to add  assert(isRectangular(m1));  inside the precondition of every function that accepts a 2D array. This is bad. A solution to this problem is to define a n-dimensional "rectangular" array type in Phobos.

About VLAs and VLA types I have an enhancement request:
http://d.puremagic.com/issues/show_bug.cgi?id=5348

------------------------

The Board variable of type Table is then defined and filled with chars. The Ada languages needs no casts here, but it makes sure Board is rectangular and it contains only the chars allowed in the ABC enumeration, otherwise it gives errors.

The D code has several problems:
- It seems to need casts.
- The 2D array is not rectangular, the "BBBBBBB" is shorter. So later I have to test this manually, maybe even at runtime.
- The cast() is a blunt tool, it performs no tests, so I am adding a "DDDDDDD" to the matrix, that's bogus.

To face one of such problems some time ago I have suggested to use to! to convert enums safely:
http://d.puremagic.com/issues/show_bug.cgi?id=5515

With it the board definition code becomes:

Table board = [to!(ABC[])"AAAAAAAA", to!(ABC[])"BBBBBBB",
               to!(ABC[])"CCCCCCCC", to!(ABC[])"DDDDDDD"];

That allows me to catch at run-time one of the bugs, it refuses "DDDDDDD". But refusing it at compile-time is much better. Being D a language that requires me to pay the price for static typing, I'd like to receive the full advantages of static typing, this means good built-in compile-time sanity tests.

The general topic of enum conversions (in both directions) looks too much ignored to me, both in D design and Phobos design:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=136114

Bye,
bearophile


More information about the Digitalmars-d mailing list