Trying to understand multidimensional arrays in D

Rekel paultjeadriaanse at gmail.com
Tue Dec 22 04:47:13 UTC 2020


On Monday, 30 January 2017 at 07:33:34 UTC, Ali Çehreli wrote:
> As others have said, D's array definition is natural because 
> unlike C's inside-out (or is that outside-in?) syntax, it 
> follows from the alias syntax. Replacing History inside main 
> with Matrix[], etc.:
>
>     History history;    // is the same as:
>     Matrix[] history;   // is the same as:
>     Row[4][] history;   // is the same as:
>     int[4][4][] history;
>
> Ali

Defending array-notation by giving an example of explicitly not 
using declared aliases makes no sense to me.
When I define 2d arrays, or index them, I think in row -> column 
terms (often math notation for matrix size being; 'rows x 
columns'), or more generally in big -> small terms, which is 
clear when using the consistent left->right notation, big picture 
first followed by detail, honestly the whole concept of 
encapsulation;

> History history;
> Matrix[] history;
> Row[][4] history; // collection of rows, stored in a dynamic 
> array (top level), each containing 4 (in detail).
> int[][4][4] history; // collection of integers, stored in a 
> dynamic array (top level), containing 4 rows (->middle level->) 
> of 4 columns (in detail),

Of course, one can also prefer storing in columns, instead of 
rows, even glsl uses column-major order, just change 'Row' to 
'Column' and you're set.
My argument here of course rests on outside->in thinking, which 
one can reverse consistently. I would be fine with that.

At heart however, this declaration design leads to inconsistency.

>    int[1][2] history; // 1 columm, 2 rows
vs
>    int last_element = history[1][0] // row 1, column 0

This makes no sense to anyone used to reading left to right, or 
even right to left.
Honestly, reversing reading-order when indexing & declaring is 
the worst idea I could imagine if consistency and readability 
were your goal. It doesn't make more sense because you're reading 
'outward', that would mean I would have to read both left to 
right _and_ right to left.

The argument Jonathan M Davis gives in this regard hold no water 
for me.
> Like in C/C++, types are mostly read outward from the variable 
> name in D. In both C/C++ and D,
>
> int* foo;
>
> is a pointer to an int. It's read outward from the variable 
> name, so you get the pointer and then what it points to. 
> Similarly,
>
> int** foo;
>
> is a pointer to a pointer to an int.

Feel free to read them the way you want, but personally, I read 
int* foo as 'integer pointer', which is not 'outward'. Your 
argument is only based on personal reading preference, but with 
it you remove indexing consistency & introduce boustrophedon.

You don't even always have the variable name;
> ... = new int[1][2]
vs
> ... = new int[][](2, 1)

If you were to ask someone with no prior coding experience how to 
access a predefined declaration, given a onedimensional 
explanation, I'm certain they would default to standard western 
reading order, no matter the presence of a variable name.

I'm surprised this thread is 3 years old by the way, sorry for 
that, just noticed this is how D handles multidimensional arrays 
(I may add a note about this to the tour suggestions).
It saddens me quite a bit, as I see it as a big design flaw and 
quite a turn-off, "unfortunately one that can't be fixed" as 
Profile Analysis put it.

> Have a nice & safe christmas!
> - Rekel, the disproportionally active forum . . . person (sorry)


More information about the Digitalmars-d-learn mailing list