"An array’s whole purpose is to be a mass of mutable state. Mutable state is hard for both humans and compilers to reason about. It will be hard for us to write compilers in the future that generate performant multi-core programs if developers use a lot of arrays."
How does this conclusion follow from the premise? It also completely ignores that arrays are the natural expression of data in data parallel programs. Nearly all high performance parallel numerical code leverages arrays heavily (OpenMP, MATLAB, various GPU languages).
"If you are writing such an API, wrap the array in a ReadOnlyCollection<T> and return an IEnumerable<T> or an IList<T> or something, but not an array. (And of course, do not simply cast the array to IEnumerable<T> and think you’re done! That is still passing out variables; the caller can simply cast back to array! Only pass out an array if it is wrapped up by a read-only object.)
That’s the situation at present. What are the implications of array characteristics for the future of programming and programming languages?"
This appears to be a correct criticism of the mechanics of arrays in C#, but I don't see how that generalizes to the topic of programming languages in general. For example, we might use some sort of copy on write approach to preserve single copy performance when not changing the array is the common case.
"Clock speeds have stopped increasing, transistor density has stopped increasing"
AFAIK transistor density is still tracking Moore's law and is expected to do so for quite some time (see SIA roadmaps).
"Parallelizing in a world with observable side effects means locks"
This ignores a whole class of wait free data structures. Some of the most interesting parallel langauge tools are built around such structures. For example, cilk is some extremely smart code centered around wait free dequeues.
"The “C” programming language is all about mechanisms. It lays bare almost exactly what the processor is actually doing, providing only the thinnest abstraction over the memory model."
This is a common misconception that leads to many bugs and performance problems. Modern compilers make dramatic transformations of programs. The connection between what we assume based on the c abstract machine model and what the processor actually does is rather complex. My favorite example of this is how consuming function arguments that are pointers into temporary variables at the top of a function body actually generates shorter faster code. This is because it tells the compiler aliasing between the pointers is impossible. However, if you're using the misguided "my c is close to what the processor does" perspective you'd incorrectly assume these assignments result in a lot of wasted work.
I'm not even a c programmer and I know this. I'm quite tired of seeing this conceptual mistake from otherwise extremely knowledgeable people.
"Arrays demand imperative code, arrays are all about side effects, arrays make you write code which emphasizes how the code works, not what the code is doing or why it is doing it."
Entirely incorrect. For example, one can elegantly express many parallel algorithms as binary recursion with an associative combining operator over trees of arrays. This is a very declarative way of programming that is both elegant and maximally expresses parallelism. See the various presentations by Guy Steele for a very clear presentation of this perspective.
As a summary, I'm impressed by the posters knowledge of C# and how deeply he's considered this problem, but I think at the root of his thinking is an assumption that nearly all languages will be similar to C#. I disagree, and I think languages that center on nested data parallelism over arrays will play a major role in the future of programming.