3 ms·
Rust’s borrow checker does a nice job of formalizing the ideas in this post with & and &mut (shared reference and exclusive/mutable reference, respectively). T
by hedora 3y ago
Rust’s borrow checker does a nice job of formalizing the ideas in this post with & and &mut (shared reference and exclusive/mutable reference, respectively). The unsafe keyword (and the interior mutability pattern) provides exactly the right escape hatch for things like TableInsert and the join operation in the post.
People like to talk about its memory safety, but it’s the fact that the compiler checks for data-race freedom that really sells rust for me.
Languages like Java claim to be memory safe and type safe, but what does that actually mean if a concurrency bug means you have multiple CPUs stomping over your objects’ internal state in race?
- jjtheblunt 3y agoJava doesn’t claim quite to be type safe considering type erasure is built into its spec, so that, by runtime, containers (for example) might be surprised by a runtime appearance of an object type not checked for or known at compile time.
- lmm 3y ago> Java doesn’t claim quite to be type safe considering type erasure is built into its spec, so that, by runtime, containers (for example) might be surprised by a runtime appearance of an object type not checked for or known at compile time. Erasure has nothing to do with type safety; ultimately almost all types are "erased at runtime" since we have Von Neumann architecture where effectively everything is a byte/word, but this does not mean mechanical computers cannot run typesafe languages. Java reflection is arguably less safe due to type erasure, but reflection is almost inherently type-unsafe in the first place. (Java does have type unsafety via e.g. covariant arrays, but that's a design choice, not a fundamental limitation)
- ackfoobar 3y ago> type unsafety via e.g. covariant arrays It's ironic when you think about it. The compiler enforced type safety is often argued as not type safe because they are erased at runtime; but the actual type unsafety has a runtime check.
- lmm 3y ago> The compiler enforced type safety is often argued as not type safe because they are erased at runtime; but the actual type unsafety has a runtime check. Were you trying to make the point that the biggest type safety hole in Java is in the one part where you have collections with unerased types? Because yeah that's kind of ironic.
- saghm 3y agoThis isn't due to type erasure though, it's due to allowing fallible subtyping; in particular, it shouldn't be possible to assign an array of a subtype to a variable of an array of a supertype. For example: class Animal {} class Dog extends Animal {} class Cat extends Animal {} ... Animal[] animals = new Dog[1]{}; animals[0] = new Cat(); The compiler could easily stop this issue by making the assignment of the `Dog` array to the `Animal` array an error because after the assignment, it's already impossible to add anything that's not a `Dog` to the array anyhow. Type erasure doesn't change this because regardless of any knowledge of the type at runtime, there's nothing reasonable to do but throw an exception because a `Cat` can't be put into a `Dog` array. I think the focus on type erasure is also a bit of a red herring because Java _does_ actually allow introspection of types at runtime via reflection, whereas Rust doesn't provide this. What information is available at runtime isn't really a factor because type safety is a property that's enforced at compile time.
- gpderetta 3y agoJava gives enough concurrency guarantees in the face of data races to maintain the integrity of the runtime and memory safety.
- pornel 3y agoBut not integrity of the program itself. You can still have data loss and garbage results. I really like the borrow checker and Rust's Send/Sync thread-safety markers, because they nudge towards cleaner thread-safe architecture, and give compile-time guarantees that work even across complex code, all kinds of collections, and 3rd party dependencies.
- riku_iki 3y ago> But not integrity of the program itself. You can still have data loss and garbage results. curious what do you mean here? Java has many utils for concurrent programming, e.g. atomic variables, synchronize blocks etc.
- dwattttt 3y agoThe distinction they might be going for is the difference between guarantees and helpful utilities; good utilities can provide guarantees, but there's a lot to be said for default-safe and a safety culture
- pornel 3y agoJava only promises to protect integrity of JVM itself, not your data. If you accidentally write to a non-concurrent collection from multiple threads, it's not a program-corrupting Undefined Behavior like in C/C++/golang, but it can still misbehave by corrupting the collection itself, causing it to mangle or lose data, or in the best case throw an exception. Either way you don't get the intended program behavior, and you may be unaware of using a wrong collection type until you create an invalid access at compile time. This is different from Rust, where thread-safety is part of the type system, so multi-threaded code that could write to a shared HashMap instead of a ConcurrentHashMap just won't compile with a type error.
- Verdex 3y agoTo me, I don't even need a multi-threaded system to want Rust's ownership system. Too many defects that I've encountered in the past have been centered around the detective work that goes into whether or not you happen to want spooky action at a distance. Ah, in this instance we've created a list with objects in it and someone somewhere else is modifying it. This is causing the defect. But in this instance we've created a list with objects in it and then someone is creating new deep copies of those objects so that someone somewhere else can no longer modify it. And THAT is causing the defect. Rust makes this process significantly more explicit (although, I suppose someone could go a little crazy with RefMut and/or &mut and you end up back in the same place where you started with other lang). The fact that this also makes threading much easier is very much welcome to me.
- johnnyjeans 3y agoIt's a nice idea, but I find the conceptualization/implementation of it to be rather inelegant. It feels like it overcomplicates and goes a long distance to achieve the same effect as an affine type system. It makes reading and writing and conceptualizing about the code that much more annoying. I don't want to be forced into thinking about imperative code in terms of objects and ownerships, that's way too opinionated for my tastes. I find it much comparable to how modern C++ template metaprogramming goes to great lengths to achieve the same capability as a dependent type system, but again it's somehow even more annoying and grating to read and write than the most proof-laden example of something like Idris. I don't want to use a language that feels like an amateurish hackjob. Just give me something approximate to ocaml syntax with low level memory control and an affine type system. Please. That's what I want Rust to be. Not a frankenstein's monster that seems in direct competition with C++ to be the most needlessly complicated and ugly language possible.
- Verdex 3y ago> It's a nice idea, but I find the conceptualization/implementation of it to be rather inelegant. Everyone is welcome to their own opinion and sense of style. Our world is better off for the one that you hold. > Just give me something approximate to ocaml syntax with low level memory control and an affine type system. Eh, the beggar cannot also be a chooser. Your desire may be good, but no one is compelled to make it a reality. Our environment experiences a glut of frontend and backend libraries for building your own programming language. As well as guides aplenty to show you the way.