Hacker News new | ask | show | jobs
by vbezhenar 1301 days ago
IMO if you would forget about borrow checker, Rust is awesome language by itself.

I'm not sure if it's even possible, but I think that if GC were introduced to Rust as an optional part, it would make Rust suitable for CRUD apps.

Like all low-level libraries are written with borrow checker and you can write your code with borrow-checker or GC, your choice. So you'll still get superior performance compared to any other GC languages, because your standard library is incredibly fast. And your code will use GC because your code does not matter from performance PoV. And if some function matters - you use borrow checker in that function, so it's fast.

Also green threads might be a good addition. It seems that modern computing reinvents it all over again. Golang, Java. Async/await is hard, people want to write blocking code and get good scalability at the same time.

We need a silver bullet programming language. Period. Suitable to write CRUD and MCU firmware at the same time. Until this silver bullet is not found, we will reinvent new languages.

3 comments

This is the kind of attitude that will send Rust the way of C++.

Features cost, even optional features. No programming language can or should try to be everything to everyone: to attempt it is to serve no one very well at all, because you split the focus of the language development between too many use cases and you complicate the language so thoroughly that onboarding a new programmer becomes an exercise in re-education about which subsets are acceptable in the given organization.

Rust's niche is safely managing memory without a GC. If Rust adds a GC, even an optional one, it will have lost its soul.

Not only that, but the borrow checker also handles safety concerns. Rust's concurrency safety story ("fearless concurrency") is literally built on the back of ownership and borrowing.
Oh, wow, yes. I confess I skimmed the part about green threads.

I think OP doesn't understand that runtime features like GC and green threads have a cost, and Rust is designed around a making it safe to avoid that cost. Most of Rust's features don't make sense in the context of a managed runtime—what you would be left with is basically a subset of OCaml with C-style syntax and optional mutability.

> Most of Rust's features don't make sense in the context of a managed runtime

I don’t think that’s entirely true actually (which is why linearity is explored in languages like haskell).

For instance Go makes it easier to trigger data races, which undermine memory safety. This is a managed langage “built for concurrency” where using concurrency means memory safety is at risk.

And that’s not recent news, Russ Cox himself wrote about it back in 2010: https://research.swtch.com/gorace

True, but linearity/affine types applied carefully in the context of a managed runtime would look quite different from Rust's borrow checker. The reason why Rust's borrow checker is so infamous is because Rust has to prove everything at compile time. Bringing affine types to a GC language would most likely involve making them opt-in (or only triggered in concurrent situations), while making linearity optional in Rust would undermine its foundations.
You can opt into runtime checking in Rust via interior mutability. Cell<>, RefCell<>, Rc<>, Arc<>, Mutex<>, Rwlock<> are constructs that involve varying levels of runtime checking - most of these will be way more efficient than GC. It's even simpler to use .clone() in order to effectively do away with any requirement for linearity.
Green threads have been totally superseded by current async support in Rust. That's why they're no longer part of the language itself.
Technically green threads were removed when rust was moved “down the stack” back before 1.0: green threads would mean requiring a runtime (scheduler & al) which is problematic when targeting foundational libraries and embedded programming, it makes integrating with other systems a lot harder.

Async being opt-in means the people who don’t need it can avoid it, though it’s not always great when e.g. the premier HTTP client of the ecosystem provides a “blocking” interface which iirc just starts a runtime and delegates to the async interface.

Ironically very early prerelease versions of Rust had a GC (and also Go-style fibers).

I think, however, a lot of people would love to see other GC languages take up the safety promises that Rust provides (especially concurrency).

A framework for "pluggable" and optional GC could be very helpful for dealing with the rare case of general graph-like data, where there really is no feasible alternative in terms of more explicit memory management. This will probably be done as a natural outcome of stable support for "local" allocators, which is already planned in Rust itself.
I feel like writing code that satisfies the borrow checker isn't that hard if you intuitively understand the lifetimes of the things you're dealing with. In C++ you have to do this anyway, so having the compiler help actually decreases the cognitive burden. I feel like desiring garbage collection is mostly a code smell, because it indicates that lifetimes and ownership are not obvious. Sometimes that'll legitimately be the case due to shared ownership, but there are facilities in both Rust and C++ for that.
Also green threads might be a good addition. It seems that modern computing reinvents it all over again. Golang, Java. Async/await is hard, people want to write blocking code and get good scalability at the same time.

This is the basic win of Go. Go's "goroutines" are preemptable. So there's no need for an async/thread distinction.