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)