> The correct way is to write > int arr[4]; > and to interpret it as "arr[4] is an int"
>> No. The "interpretation" is "arr is an array of ints", and that is its type.
I would have been happier if I had found my explanation interpreted in a more generous way. But that's basically what I was saying (and literally what I was saying in another comment).
As to the rest, the advantage of the C approach to type declarations is that there is no type declaration syntax. Just expression syntax. And that it's very terse.
> That's exactly why most languages said: "if we're changing the type, we're going to reflect this in the type". In a better world the examples above would be something like
There's a problem in that your proposed syntax is not even properly parseable. How would a parser recognize that your lines start with types i.e. are variable declarations? For example the example "* (int[]) arr", it would start reading the asterisk and the opening parenthese as an expression, and then suddenly find a type name (int), and could then not throw an error if it was one, but had to start all over again and try to parse the whole thing as a type declaration. That's not exactly nice - good syntax is parseable with a single token of lookahead. That not only makes parser implementations easier, but is also easier to read for humans and leads to better error detection.
Apart from that I think that your examples are about what D does, and this stuff is WORSE in my opinion. While the real problem with C declarations, which is the need to thread a symbol table through the lexer/parser, is still existent in D syntax (I believe), it introduces other problems:
How do you use an array that was declared as "int[5][10] arr"? Using it as "arr[4][9]" is an error: it must be "arr[9][4]". In other words, your approach to type declarations requires the programmer to constantly turn around declarations in his/her mind, which leads to lots of mistakes. It gets even harder when you add pointers / functions, for example "int* [5][10] arr" I believe you must access as "* arr[9][4]", or whatever the D dereference syntax is.
Java can afford to let you declare "int[][] arr = new int[5][10]" and let you access "arr[4][9]", at the cost of cheating. Java can "turn around" the dimensions because it doesn't actually have an "algebraic" type syntax, which it doesn't need because it doesn't have pointers / function pointers so there is no interaction there.
That's one of the reasons why most newer languages have the type to the right of the variable name, and types grow to the left (towards the variable name). For example, "let arr: [5][10]int" you can access as "arr[5][10]" which is easier, but that principled approach to syntactic construction of types also puts requirements on the expression syntax: For example, "let arr: [5][10]* int" would have to be accessed as "* arr[5][10]", which is weird - or the expression syntax must be changed to use a postfix dereference operator.
In short, it's not as easy as you thought, and the C syntax is in fact pretty smart. And from a practical standpoint I prefer the C way very much because it's so much terser and has less punctuation than all the alternatives. The only thing that annoys me is the lexer hack.