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

Reply via email to