FP is good for adapting to threading, but it has difficulties, when applied to things like GUI programming, async communications, or device control (places that need threading).
A lot of languages are getting things like async/await/actor, etc., but even that is still too low-level for a lot of programmers. It can easily turn into a lot of single-threaded code.
It needs to be completely under the surface. Swift does that with generics (I suspect other languages do it, as well). For example, you can say Array<Int>, or [Int]. They mean the same thing, but one does not have the generic syntax.
If we can do similar stuff with things like mutexes and syncing, then it will go a long way towards highly performant, safe, code.
It's interesting that you choose Swift as an example, because I think in some ways Swift does a poor job of accommodating async using the "bubble wrap" approach.
Specifically I am talking about the default of using atomic reference counting on all references. This makes it somewhat idiot proof at least with respect to avoiding NPE's, but it comes at a huge performance cost (especially on x86 which I guess is becoming less of a concern for Swift code).
I think this is a fundamental issue: a big part of the benefit of concurrency and parallelism is supposed to be increased performance. However a lot of the ways to make concurrency "generally safe" tend to hamstring performance, because you have to protect against all the different types od errors programmers can make, which basically means a lot of expensive synchronization.
Maybe there is a way to hide this completely, as you say, in a performant way. To do this, I think you would almost have to have either some kind of really clever risk-free data structures, or else a very smart compiler.
Another approach might be to keep concurrency at arms length from the average programmer. I.e. hide 90% of it inside of libraries, and expose safe interfaces which the programmer interacts with in a mostly synchronous way.
> I think in some ways Swift does a poor job of accommodating async using the "bubble wrap" approach.
I agree. Async/await has a "kludgy" feel to it (to me). It's "added on," not "embedded in." But I'm not a language writer, so I don't have alternatives to offer.
I was talking about how it does generics. I think it does that quite well.
I agree that compilers and schedulers should be enforcing partial orders of concurrency. I talk of various multiversion concurrency control ideas in my ideas4 page.
As an example I think Thread yield should take an argument for a matching data structure that when the state of that data structure changes you trigger rescheduling at that point and avoid a busy wait.
A lot of languages are getting things like async/await/actor, etc., but even that is still too low-level for a lot of programmers. It can easily turn into a lot of single-threaded code.
It needs to be completely under the surface. Swift does that with generics (I suspect other languages do it, as well). For example, you can say Array<Int>, or [Int]. They mean the same thing, but one does not have the generic syntax.
If we can do similar stuff with things like mutexes and syncing, then it will go a long way towards highly performant, safe, code.