Trying to understand multidimensional arrays in D

Ali Çehreli acehreli at yahoo.com
Tue Dec 22 07:19:49 UTC 2020


On 12/21/20 8:47 PM, Rekel wrote:

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

Reading 3-year younger Ali's message, I still agree with him. The 
aliases were not given to defend D's array syntax. They were just an 
additional information which I do use occasionally to simplify my code.

 > When I define 2d arrays, or index them, I think in row -> column terms

Everybody have their own mental model. Because C, C++, D, three 
languages that I am quite familiar with, don't have 2d arrays, 
personally, I never felt comfortable with that mental model. I don't 
think C's array syntax is left-to-right or right-to-left, it's either 
inside-out or outside-in. As soon as I learned about D's array syntax I 
felt happy. Consistent...

 > (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;

Ok.

 >> Row[][4] history; // collection of rows, stored in a dynamic array

But that's not consistent. If array syntax is "type followed by square 
bracketed stuff", then your history must be

   Row[4][] history;

   Row[4] -> Four rows

Now, if we call that T, a history of those is

   T[]

Replacing T with Row[4]

   Row[4][] history;

That's what understand from consistency. What other consistent mental 
model is there to accept int[] as an array of ints but when it comes to 
an array of Row[4]s we should write Row[][4]? It's not logical nor 
consistent. It's a remnant of C, where the creator decided to make the 
definition and the use the same (or similar). Well, that did not work 
for me. And the creator agreed in a interview (which I am not motivated 
to search for now) that he might find a better syntax for C array but it 
was too late then.

 > At heart however, this declaration design leads to inconsistency.

I disagree and I don't even understand.

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

You seem to expect the language to parse history[1][0] as a whole. (?) 
However, history[1] is an expression by itself. There is one thing that 
history[1] returns and that is the second element of that array. [0] is 
and should be applied to whatever history[1] expression produces. Now, 
that's consistent.

 > Honestly, reversing reading-order when indexing & declaring is the worst
 > idea I could imagine if consistency and readability were your goal.

I argue the complete opposite for the same reason: consistency and 
readability.

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

I always read from left to right: T[]. That is the array syntax. And 
arr[i]; that is the array element access syntax. Everything else falls 
into place with those definitions.

 > The argument Jonathan M Davis gives in this regard hold no water for me.

Neither to me. I am simple person. Definition: T[], use: arr[i]. Done. :)

 >> Like in C/C++, types are mostly read outward from the variable name in
 >> D. In both C/C++ and D,

Perhaps because I'm not a native speaker, I have never ever read any 
definition from right-to-left or inside out or outside in.

 >> int* foo;
 >>
 >> is a pointer to an int.

To me, it has always been an "int pointer".

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

No: "int pointer pointer". :)

 > Feel free to read them the way you want, but personally, I read int* foo
 > as 'integer pointer', which is not 'outward'.

Thank you! Me too! :)

Let me try the history example:

   Row[4][] history;

Row array (of 4) array.

 > just noticed this is how D handles multidimensional arrays

I think that's the source of the disagreements: D does not have 
multidimensional arrays. C and C++ don't have multidimensional arrays 
either.

 > It saddens me quite a bit, as I see it as a big design flaw and quite a
 > turn-off

Fully disagreed: D's array syntax makes me happy; designed right. :)

 > , "unfortunately one that can't be fixed" as Profile Analysis
 > put it.

Phew! :)

 >> Have a nice & safe christmas!

Same to you! <3

Ali




More information about the Digitalmars-d-learn mailing list