That almost sounds like an endorsement. I’ve been holding off learning Rust. However, it seems like Rust adoption is reaching a tipping point.
That almost sounds like an endorsement. I’ve been holding off learning Rust. However, it seems like Rust adoption is reaching a tipping point.
Rust is quite an easy language to learn and a pleasurable language to use, due to its modern ergonomics and internal consistency. Give it a try. The only trick is that Rust newcomers actually need to read up on Rust borrow checker and lifetime annotations first, as opposed to learning Rust only through hacking with it. Those two concepts are unique to Rust and need to be well understood beforehand to avoid frustration.
[1] - https://doc.rust-lang.org/book/ch15-04-rc.html
[2] - https://doc.rust-lang.org/book/ch15-05-interior-mutability.h...
[3] - https://doc.rust-lang.org/book/ch15-05-interior-mutability.h...
Talking about which object "owns" another that a pointer "outlives" what it points to are totally normal parlance for C++ developers and completely foreign to a lot of other folks.
There are a lot of similarities! The type systems are similar, with some name changes (sum types -> enums, typeclasses -> traits). Pattern matching is basically the same. Haskell uses (lazy) lists mostly the same way rust uses iterators. Ownership is new, but imposes some of the same requirements that immutability does (no cycles without shenanigans[0]). Rust requires that values are aliasable XOR mutable: Haskell does too (they're always aliasable and never mutable).
But someone who understands Haskell, may still find some memory stuff clumsy.
Here's a reasonable program to write in Python (wave hands here, my python is rusty)
queue = [root]
for node in queue:
if !node.visited:
# ... visit the node ...
node.visited = True
for child in node.children:
queue.insert(child)
Here's that in Rust. let mut queue = VecDeque::new();
queue.push_back(root);
for node in &mut queue {
if !node.visited {
// ... visit the node ...
node.visited = true;
for child in &mut node.children {
queue.push_back(child);
}
}
}
This will not compile, at all. You need to do a lot of work to restructure the data structures in Rust to get that reasonable program to run soundly. Now that's a good thing, because this would be invalid in C/C++ too due to iterator invalidation and lifetime issues, but it's the kind of thing that people who haven't seen a block of code segfault due to a `push_back` before would be confused by.It's rather rare for a programmer to need to learn about memory safety when compilers in managed languages just solve it for you, and in other systems languages they assume you already know it (or don't care that you can write unsafe programs).
There's just that additional conceptual burden when learning Rust and why programs that seem syntactically correct and safe are forbidden.
edit: in fact, if you specifically use a deque in Python the way you are in Rust, Python will throw a "RuntimeError: deque mutated during iteration". This is just a bad approach in any language, honestly.
For anyone coming from a GC language, Rust is a huge change.
It's funny. I hear two different things, all the time. "Rust is easy to learn" and "Rust has a steep learning curve". Personally, I found it to be the latter, and that's as a serial dabbler/language polyglot. I had a bear of a time wrapping my head around lifetime annotations, and needed someone already familiar with them to sherpa me through that stage.
I think it does a disservice to say, "Rust is easy to learn modulo these two really challenging concepts, plus some other things you are likely unfamiliar with". Python is easy to learn. C++ is hard to learn. I'd rate rust as medium difficulty.
It sure is enjoyable though, I don't think that's ever in doubt.
https://www.microsoft.com/en-us/research/project/project-ver...
They used to have this great site were you could interact with them all: https://web.archive.org/web/20180130101736/https://www.rise4...
Source: I'm a former member of RiSE
It is also where F# started, although they seem not yet to know where to push it, or if it was a good idea to actually box it in VS 2010.
https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html
This needs to exist in Rust for it to get adopted, because forcing good developers to get explicit with code for memory safety when they are doing simple operations is going to result in them ignoring the language.
So eventually code bases are going to be exactly like C++ code bases - C++ has a standard library and smart pointers that eliminate a lot of errors with dangling pointers, and if people use those exclusively (or better yet, the language disallowed any C style pointers or arrays), the language would be dramatically more safe.
If you want to improve development, focus on smarter compilers/interpreters, not languages.
> [Rust] [will be] driven into a shit state. Specifically because of [unsafe Rust]
Using unsafe Rust is actually frowned upon in the Rust community, unless you specifically need it in order to interface with another programming language (e.g., Foreign Function Interface), work around some OS issue (e.g., memory pinning for Linux driver development) and so on. Otherwise, you are supposed to always write safe Rust code.
Way more than unsafe Rust, what worries me is the potential future, long-term language feature bloat. I wholeheartedly do hope that Rust core team will keep the language as simple and consistent as humanly possible.
> If you want to improve development, focus on smarter compilers/interpreters, not languages.
Well, in order to get a smarter compiler, you need new language features to be able to feed additional information about programmer's intent into that compiler - hence Rust's new language features, for example (memory reference) lifetime annotations that all newcomers have a problem with :).
>Well, in order to get a smarter compiler, you need new language features to be able to feed additional information about programmer's intent into that compiler
Yes and no. There are some things you want to specify for compiler to check, but a lot of behavior can be inferred from the code. Think about some backend server functionality for a website that has to do processing on some json data. You could take that code in python and write absolutely safe C code, and the process to translate it wouldn't be that hard.
You can't use smart pointers exclusively, because there is no "smart observational pointer", and there cannot be one, because that would be a reference type checked by a borrow checker, which is exactly what rust uses.
You can emulate it with shared pointers, but then you're left with basically a reference counted language. Why not using swift at this point? Also this creates a semantic impedance mismatch that tends to manifest with cycles.
Source: walked a codebase that would (ab)use shared pointers
Sure, there are some things that Rust makes nice, like compile time checking for errors, however with C++ codebases, they will just result in runtime errors rather than usable exploits.
That's...exactly what Rust is doing with their compiler, which checks ownership and lifetimes, so I don't understand your point here. Maybe they didn't need to write a whole new language, but why not add modern features like pattern matching along the way?