www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Enum matrix example

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
May 26 2011