Hacker News new | ask | show | jobs
by skohan 1660 days ago
I think part of it is because computer science hasn't really nailed the right abstraction for concurrent code execution.

For instance, C is a great abstraction. You take assembly language, abstract away manual management of registers with variables and pointers, add structured types to describe memory layout, standardize flow of control operations, and add functions to enable code reusability, and you have something which is very easy to work with and also to understand. It's not 100% on par with assembly in terms of performance, but it's pretty darned close, and with a little bit of practice it's very easy to look at a block of C code and basically understand what equivalent assembly it compiles to. It's a great abstraction, and it's no wonder that a vast majority of the languages which have come after it have borrowed most of its major features.

I would argue we haven't really had a "great abstraction" to the same level since then*. There have been efforts to abstract away memory management the way register management has been abstracted away, and many of them have been successful for a lot of use-cases, but not to the point that everyone can forget about memory management the way the vast majority of us can forget about register management. Garbage collectors can be too slow or too wasteful for a lot of use-cases, and you need essentially another program you didn't write to pull it off. In a GC'd language it's not so trivial to look at a block of high-level code and predict what your CPU will do. There are other approaches: like the structured approaches of Rust and Swift which are quite interesting, but they're far from proven at this point.

Similarly I think we're not quite there yet with concurrent programming. As far as the transparency topic, a lot of async implementations are more in the direction of garbage collectors, where the compiler rips apart your code and builds a state machine in its place. It's not hard to believe that the result will be difficult to work with and reason about in some cases.

And maybe the problem is that most approaches to async are trying to cram concurrent execution into that C-like abstraction, which is such an elegant abstraction for single-threaded execution exactly. Maybe concurrent programming needs to be re-thought from first principals, with different primitives involved.

*Aside: if there is another "great abstraction" on the horizon, I believe it to be ADT's. That is a feature of programming which feels like a clear step forward with no clear downsides. It's a shame that they haven't been included in Zig.

1 comments

Zig has tagged unions and the corresponding switch expressions, is that not equivalent?
I was not aware of these, either it was added since I kicked the tires on Zig or I just wasn't aware of it, but yes it looks pretty good!

The one drawback I see is that it seems a bit verbose: i.e. the tag set itself has to be declared as a separate enum, and then the tags need to be repeated inside the union.

So it looks to be slightly bolted-on and unergonomic (similar to TypeScript's implementation) but I haven't worked with it so maybe I am missing something.

You can use union(enum) to avoid having to write a separate enum definition for tags and std.meta.FieldEnum() exists should you also want to derive an enum from the union later on.