For example:
fn foo<'a>() -> &'a [u8] {
let v = vec![0, 1, 2];
// returns a value referencing data owned by the current function
v.as_slice()
}
vs Go's: func foo() []uint8 {
// subject to escape analysis, but code like this would likely return
// a fat pointer into the heap--no complaints because there's a GC.
return []uint8{0, 1, 2}
}
> One of the beauties of Rust is that you can write highly parallel code and if it compiles it works. Meanwhile Python languishes behind the GIL. GC does not even attempt to solve multithreaded memory access.Python's GIL is unrelated to GC, but yes, Rust's borrow checker guarantees correct parallel access of memory. But I think this benefit is overblown for a couple reasons:
1. contrary to popular opinion, if you've learned how to write parallel programs, it's not tremendously difficult to write them correctly without a borrow checker. In my experience, whatever time I've saved debugging pernicious data races is lost by the upfront cost of pacifying the borrow checker. Maybe this wouldn't hold for people who aren't experienced with writing parallel code (but I imagine such people would have a harder time grokking the borrow checker as well).
2. most data races in my experience aren't single threads on a host accessing a piece of shared memory, but rather many threads on many hosts accessing some network resource (e.g., an S3 object). The borrow checker doesn't help here at all, but you still have to "pay the borrow checker tax".
Again, this isn't a tirade against the borrow checker, but an insistence that tradeoffs exist and it's not just a "you're just doing it wrong" sort of thing.