6 ms·
You need ownership tracking even in languages with GC because you will be dealing with resources that are more than just memory, and with those GC isn't really
by chousuke 5y ago
You need ownership tracking even in languages with GC because you will be dealing with resources that are more than just memory, and with those GC isn't really enough. A GC alone doesn't really help you deal with concurrent access, either. If you don't have a borrow checker, you will be essentially doing the same work manually as you're reading and writing code.
Rust's ownership tracking is not only about memory safety. It can also help you with other kinds of resources whose ownership you can encode using the type system.
- masklinn 5y agoYes indeed, I'd like it if other languages had ownership and borrowing. Hell, I'd like it if a language could actually achieve linear types without holes or being completely unusable. They could allow more relaxed GC'd normal types, whether default or opt-in, but affine and linear typing are genuinely useful properties fo reasoning about code, from both correctness and performance perspectives. One needs to look no further than the string slicing problem for that to be clear. It's not an issue in Rust, but in every GC'd language you have to pick between: 1. eagerly copying the slice, which incurs additional often unnecessary CPU and memory costs, but avoids 2. every substring operation which isn't defensively copied being a potential memory leak as you're slicing 3 characters off of a 5MB string on every HTTP request and storing that in a global map, which turns out to store the entire 5MB string you got it from Or some even more complicated magic where you only perform the copy if the substring escapes, at which point your performance and memory characteristics become wildly unstable and the mere act of extracting a function can bring the entire system to its knees.
- zetalyrae 5y ago>Hell, I'd like it if a language could actually achieve linear types without holes or being completely unusable. I'm working on this: https://github.com/austral/austral/ https://github.com/austral/austral/ The idea is to start with a simple, easily understood linear type system and then add borrowing, but without going too far in the direction where the type checker becomes a tower of heuristics and conveniences so that programmers can write normal-seeming code which magically typechecks. So you can learn how to write linear code from reading a set of linearity rules, rather than from trial-and-error against the linearity checker.
- skohan 5y agoThis seems like a very cool project! Have you ever thought about putting a simple code example right in the README? Maybe it's too early days, but I know that's always the first thing I'm looking for when I stumble across a new language.
- zetalyrae 5y agoYeah I should get around to doing that, but right now there isn't much code that succinctly showcases the linear typing features. Probably have to implement some of the stdlib for that.
- throwaway17_17 5y agoA look at your anti-features list reminds me somewhat of Zig. Obviously the polymorphism is not in the Zig wheelhouse, but there are some similar seeming paths running through the readme. Your comment had me expecting a Haskel/ML presenting language, but now I’m wondering. Where do you see the syntax going?
- zetalyrae 5y agoThe syntax is Ada-like, e.g.: https://github.com/austral/austral/blob/469403c95219c4e6853729bf5b6311c02b083f42/examples/fib/Fibonacci.aum https://github.com/austral/austral/blob/469403c95219c4e68537...
- skohan 5y agoYou need some way of managing ownership, but it doesn't necessarily need to bubble up to the user level. For instance Swift is going in the direction of leaning heavily on value semantics, plus the actor model to wrap concurrent data, to create a safe environment where the user doesn't have to think about ownership at all. Of course there's tradeoffs involved, but I think there are multiple approaches to achieve safety and user-space ownership constraints are only one of them.
- pjmlp 5y agoMost GC languages invented before Java went mainstream had value semantics as well actually, and this is one of language defects that .NET improved over Java. Many forget that MSIL is like LLVM, having all semantics to compile C++, alongside GC. Some of those capabilities weren't exposed to other .NET languages, however since C# 7 they have been improving it. As of C#10, there is little left to do versus Modula-3 or D.
- int_19h 5y agoLow-level C# could still use https://github.com/dotnet/csharplang/issues/1060 https://github.com/dotnet/csharplang/issues/1060 - then we could steal all the high-perf generic algorithms from the C++ guys, and call it good.
- pjmlp 5y agoYeah, although maybe with native function pointers and static lambdas one could try to work around it.
- pjmlp 5y agoMost GC languages have deterministic resource management, not everything is a JavaScript like GC. Borrow checker only helps dealing with concurrent access on the very special case of multithread code accessing in process data structures. Anything else that follows outside of this, like concurrent access to external resources, or via OS IPC, there is little help. https://doc.rust-lang.org/nomicon/races.html https://doc.rust-lang.org/nomicon/races.html
- tialaramex 5y ago> the very special case of multithread code accessing in process data structures. So, the thing this gets you, as the Nomicon explains, is you're data race free and so you get to have Sequential Consistency (in Safe Rust) within your program. After decades of computer programming, our experience is that humans need Sequential Consistency to think about anything that's too tricky to just write down a complete list of all cases. This is terrible news if you write machine code, since your modern CPU doesn't bother supplying Sequential Consistency in favour of going faster instead, but it's also very bad news in many languages (C++, Java, Go) where the promise is SC/DRF but you're on your own to supply that necessary data race freedom (in fact in C++ it's worse, if you can't supply data race freedom you get Undefined Behaviour). The traditional (and especially on Unix, well rewarded) solution is to give up and only write serial code. Then your program doesn't have concurrency, so it will be Sequentially Consistent. When the average computer didn't have pre-emptive multitasking this felt like a pretty sensible way to write programs. Even once the average computer did have pre-emptive multitasking (and so threads are a nice win for some problems) it did not permit simultaneous execution, most programs weren't slower for being serial. But today lots of people even own a smartphone with more than one CPU core. So hence Rust's Fearless Concurrency. Instead of an hour-long tutorial full of caveats and generalisations (to write parallel algorithms in C++) you can confidently write your Safe Rust with concurrency and the compiler will reject any fumbling attempts that introduce data races. Instead of needing to call Sarah the grizzled concurrency expert for any changes to functions in scary-but-faster.cpp you can let Bob the new girl modify the code in faster.rs, confident that either Bob's changes are actually safe or you'll spot the awful mess she made trying to pacify the borrow checker during code review.