Hi Jared —
You're very welcome! Focusing on this sentence:
In Chapel, type check errors will flag the compiler, but only as much as a developer disciplines themselves to do it.
note that Chapel does do compile-time type checking, but it's important to be clear about what that encompasses:
For examples like yours with array size mismatches, an array's size is not part of its type in Chapel (nor are its indices), so the type-checking performed doesn't protect against this case. We could still invest in generating compiler errors for simple cases like yours that used param indices, but it wouldn't technically be type-checking—more like a helpful value-check that would save time and reduce frustration (both very worthwhile things).
In contrast, things like the number of dimensions in an array or its element type are part of its type, and the compiler guards against mistakes made there. For example, the following declarations would generate errors, the first because of a rank mismatch (2D vs. 1D arrays), and the second because real values can't be assigned to ints:
var A: [1..2, 1..2] real = [1, 2, 3, 4];
var B: [1..4] int = [1.0, 2.0, 3.0, 4.0];
Note that it's frequently useful that an array's indices are not part of its type because it permits patterns like the following that assign between expressions with different indices:
var C: [1..4] real = SomeOtherArray[lo..#4];
var D: [1..4] int = [1, 2, 3, 4]; // note that the RHS array defaults to indices`0..3`
Similarly, while it might seem attractive to imagine an array's size being part of its type, practically speaking, it could cause issues or code explosions when passing arrays to procedures. E.g., imagine specializing a procedure that printed out 1D arrays for every size that was passed into it in practice.
Popping back to this part of your statement:
only as much as a developer disciplines themselves
I wanted to make sure it's clear that whether a declaration includes an explicit type or not, the compiler will still give it a well-defined static type, and will still do type-checking against it. Thus, whether you declare your variables using:
var A = [1, 2, 3, 4],
t = (0, 1, 2),
pi = 3.1415;
or:
var A: [0..3] int = [1, 2, 3, 4],
t: 3*int = (0, 1, 2),
pi: real = 3.1415;
the types and type-checking performed on both versions will be the same.
Of couse what's not done is to check that the initialization expression and the variable's type match the user's expectation. So for example, if I were thinking "I'm going to declare a boolean and a 2D array" and wrote the following:
var b = flag1 + flag2, // where flag1 and flag2 are bools
A2 = [[1, 2], [3, 4]];
then the compiler would do what I wrote, not what I thought I was writing, and make b an int (adding bools yields integers; probably I should've used | if I thought of + as "or"), while making A2 a nested array-of-arrays.
In contrast, if I were to assert the types I was expecting by specifying them:
var b: bool = flag1 + flag2,
A2: [0..1, 0..1] int = [[1, 2], [3, 4]];
then the compiler would point out the disconnect between what I was expecting to get and what I actually wrote, which might prompt me to rewrite it as:
var b: bool = flag1 | flag2,
A2: [0..1, 0..1] int = [1, 2; 3, 4];
though of course I could've written it like this from the start and ended up in the same place:
var b = flag1 | flag2,
A2 = [1, 2; 3, 4];
(note that similar situations could come up when passing an expression to a formal argument with or without a type constraint on it).
In this sense, you're correct that developer discipline can head off mistakes—typically user mistakes or mis-understandings of how the language works. But I wouldn't want you to think that relying on type inference somehow makes the compiler skip type checking or be more relaxed about an identifiers type—that's the same either way.
I love the lack of boilerplate in Chapel compared to say, C++
Thanks for saying so. I'm obviously biased, but I completely agree!
Have a good weekend,
-Brad