Exactly! And I feel R has a similar problem.
Coming from physics myself,I understand that beautiful notation can make things much easier and can be often the way to find great solutions, but proper organization will most often be sufficient.
Say m[1:2,] where "m" is a matrix. That returns a matrix. m[1,] returns something that is not a matrix. That sort of type soup breaks all sorts of things in an unhelpful manner. typeof(m[var,]) and class(m[var,]) don't reveal any information on the subject either. You need to explicitly test if you still have a matrix with is.matrix after accessing a sub-matrix of a matrix in the obvious fashion. That is an important operation. Good luck figuring that out if you don't already know what is going on; the design is awful.
The short story is to go install tidyverse and use that instead.
The problem really arises when you write m[1:n,] with the intent of getting a matrix with n rows, and n happens to be 1 at the moment, so you get a simple vector instead.
This is a problem that I have addressed in my pqR version of R, available at pqR-project.org.
In pqR, there is a new sequence operator, .., which produces a 1D array, not a simple vector. And in pqR, when a 1D array is used as an index, the dimension is not dropped, even if the array happens to be of length 1. So m[1..n,] produces a matrix even if n is one.
Well, most of the time. There's also the problem that m might have only one column, so the result will get dropped down to a simple vector for that reason. To solve this, pqR has a new way of indicating a missing argument, with _, which also indicates that you don't want the dimension dropped. So you can now get exactly the behaviour desired by writing m[1..n,_].
This is all backwards compatible, except that it's necessary to disallow use of .. in the middle of an identifier, so that a..b won't be taken as the name of a variable.
But if you mean threads programmed explicitly in R, with fine-grained, low-overhead communication using shared memory, I think it would be quite challenging to modify the current implementation to support a language extension to do this. But maybe not impossible, for some sorts of extensions.
If you write a function and need stable behavior use m[x,, drop = FALSE]. Problem solved.
No need of tideverse (which comes with its own surprises).
It's not that the language makes the project complex. It's that the projects are by a bit more complex than the language is cut out for.
> but the lack of training in proper software development...
Assuming training scientists etc. in proper software development is a good use of their time (it might be); then MATLAB is a blocker because it makes it hard/ugly to implement "proper" techniques.
Again Python fits the bill here, because its a pretty good language for novices to hack around naively in, while scaling smoothly to projects 5-10 times more complex. So that the naïf has some headroom.
Let professional language do professional things, and the advantages of various languages complement each other.
Personally, I do a lot of numerical calculus and prefer octave than numpy, just because the language is less verbose and more comfortable to use. I have converted many times ugly python+numpy code into beautiful octave. If your main and only goal is to perform matrix computations, then octave is excellent. I have never used nor needed the commercial matlab.
The python numerical stack has a rather absurd feeling in my eyes.
And that was before numerical python existed. Now, MATLAB compatibility is about the only reason to use Octave. But a better idea is to get out of the MATLABiverse altogether.
As for reasons to use Matlab:
Matlab comes with XYZ toolkit: This isactually a good reason if you know that XYZ toolkit is your core business. In general though, the Python ecosystem is far bigger that Matlab's one.
Easy for scientist: Trap. Every MATLAB using scientist I know ends up with a code base that is too complex (~1000-5000 lines of code) for the language, but is perfect for Python. (Exactly like how programmers start projects with Python that then grow too big for that language).
Admittedly falling into the trap once might be cheaper than learning Python, assuming you never need to program anything again in your life.
Vector/matrix math: Numpy has all the same vector/matrix stuff including a class which does matrix-multiply under that '* ' operator like MATLAB. But that tMatlabhat operator is a trap: '.* ' is far more common in MATLAB code and accidentally using '* ' is a common bug. This is effortlessly avoided in Numpy standard classes.