I think over time the C/C++ way is going to go the way of the dodo; IIRC, rust and go both use the prefix-[]. It creates a clear, unambiguous way of defining the type (no "spiral typing" jokes for the modern languages).
fn main() {
let mut a: [[i32; 2]; 5] = [[0,0],[0,0],[0,0],[0,0],[0,0]];
println!("{:?}", a[0]);
}
Note that the Rust array declarations are also homologous to other types in the ecosystem, such as nested Option types or nested collections (eg: Option<Option<T>> or List<List<T>>).Contrast w/the C version, where it's obvious to a skilled C programmer but you need to remember to read the bounds from right to left to determine the memory layout (ie: an array of 5 arrays of two elements each):
int main() {
int i[5][2] = {{1,2},{3,4}, /*...*/};
printf("%ld\n", sizeof(i[0])/sizeof(int));
return 0;
}
In this case you are required to mentally combine the type on the left of the variable with the bounds on the right of the variable to parse a type declaration in your head that eventually looks like the Rust version: (int[2])[5]
I've been doing a lot of professional C work lately so it's currently "swapped in", but I find that any time I pick C up after spending time away I find it ambiguous and I have to reason through the ordering of the declarations.Obviously this is all IMHO and YMMV, but this developer does find it significantly easier to unambiguously parse Rust types.
To me, [[i32; 1]; 10] is homologous to Items<Items<T, ZeroOrOne>, Unlimited>, not Vec<Option<i32>>. To me, it make more sense to put the size before the inner type (either [1; i32] or [1]i32), since you need to index the array before getting an instance of the type.