> At the end of the day, I don't need to make weird and often gross C bindings in my Rust or Go code. Is that not a huge win?
You just need to manually insert stack growth checks before all function calls in anything that can be called from go to support goroutines, because those can't live on a normal stack and still be sufficiently small to support desired go semantics. Async has similar issues, where the semantics are incompatible, which means that many things go horribly wrong in cross-language calls
Or you use a lowest common denominator and essentially treat the thing like an rpc, with a thick layer to paper over semantic mismatches.
And that's before we get to things like C++ or D templates, Rust or Lisp macros, and similar. Those are lazy syntactic transformations on source code, and are meaningless across languages. Not to mention that, if unused, they produce no data to import. But, especially in modern C++, they're incredibly important.
I've often wondered for client-side apps if a simple thread-per-goroutine model would work for Go. Sure, you'd lose some of the easy scalability. But I think that's mostly useful for server software and client apps don't usually have thousands of concurrent tasks anyway. You could also lower the overhead some for calling C libraries (which client software does more often).
You just need to manually insert stack growth checks before all function calls in anything that can be called from go to support goroutines, because those can't live on a normal stack and still be sufficiently small to support desired go semantics. Async has similar issues, where the semantics are incompatible, which means that many things go horribly wrong in cross-language calls
Or you use a lowest common denominator and essentially treat the thing like an rpc, with a thick layer to paper over semantic mismatches.
And that's before we get to things like C++ or D templates, Rust or Lisp macros, and similar. Those are lazy syntactic transformations on source code, and are meaningless across languages. Not to mention that, if unused, they produce no data to import. But, especially in modern C++, they're incredibly important.