When I was first getting started I learned so much from Amos and his INSANE deep-dives over at fasterthanli.me, basically he taught me Rust. For my 3rd video I messaged him and asked if I could base it on his article and he said 'go for it' - since then we've both found ways to go full-time in our respective worlds, and we shitpost in a private discord together :-D
This video isn't really a good intro to either my channel or the WHYs of Rust, just the syntax.
If I may signpost my own intro to Rust playlist https://www.youtube.com/watch?v=oY0XwMOSzq4&list=PLZaoyhMXgB...
And an example of one of Amos's deep-dive videos "C++ vs Rust: which is faster?" https://www.youtube.com/watch?v=VMpSYJ_7aYM
[1]: https://fasterthanli.me/articles/recursive-iterators-rust
However, 8 years later I did eventually come to love rust after learning the One Weird Trick of using indices instead of pointers.
IMvHO, Rust Ownership and Lifetime rules aren't really that hard to learn. The only trick is that a programmer cannot learn Rust exclusively by trial-and-error (which programmers love to do), trying dozens of syntax combinations to see what works. A programmer is forced to learn Rust by RTFM (which programmers hate to do), in order to understand how Rust works. That's all there's to it. It's like trying to learn to play the guitar without reading a book on guitar cords, pulling guitar strings individually at random - the music just won't happen for quite a long time, unless you're Mozart. At any rate, one can always forget Rust references (i.e., raw pointers) and use Rust reference-counted smart pointers[1], effectively writing Rust analogously to Swift.
Having seen that kind of opinion stated elsewhere, it seems what most people would like is rust minus borrowing, and I feel I would get behind that too.
It's already possible. Use Rust reference-counted smart pointers[1] for shareable immutable references and internal mutability[2] for non-shareable mutable references checked at runtime instead of compile time.
[1] https://doc.rust-lang.org/book/ch15-04-rc.html
[2] https://doc.rust-lang.org/book/ch15-05-interior-mutability.h...
I have never written a game before, so Catherine West[1] might have very good reasons for choosing ECS, but I... am not so crazy about it. ECS seems to replace Rust references (raw pointers) and/or Rust smart pointers with indexes into one, large "registry" (a container: e.g., a `Vec<T>`) of entities (e.g., `struct` instances). In other words, instead of allowing a Rust pointer (a managed memory address) to keep a piece of memory alive, ECS chooses to have a "registry" keep a piece of memory alive under a particular index, managing allocation and deallocation manually.
In a sense, ECS dumps Rust memory management in favor of... writing the good, ol', data-and-function -oriented C. Quite needlessly (?), since the same (?) can probably be accomplished with Rust reference counted pointers[2], weak pointers[3] and interior mutability[4].
----- CUT HERE -----
use std::rc::{Rc, Weak};
use std::cell::RefCell;
type WeakMutEntity = Weak<RefCell<Entity>>;
struct Entity {
related: WeakMutEntity,
}
impl Entity {
fn new(related: WeakMutEntity) -> Self {
Self { related }
}
fn use_related(&mut self) {
let Some(related) = self.related.upgrade() else { return; };
related.borrow_mut().use_related();
}
}
let entity1 = Rc::new(RefCell::new(
Entity::new(/* null */ Weak::new())));
let entity2 = Rc::new(RefCell::new(
Entity::new(Rc::downgrade(&entity1))));
entity2.borrow_mut().use_related();
----- CUT HERE -----If the above does not get the job done, the solution shouldn't be to just abandon the Rust borrow checker; the solution should be to get the Rust Gods to optimize the available pointer types syntax-wise and/or performance-wise.
[1] https://www.youtube.com/watch?v=aKLntZcp27M
[2] https://doc.rust-lang.org/book/ch15-04-rc.html
[3] https://doc.rust-lang.org/book/ch15-06-reference-cycles.html
[4] https://doc.rust-lang.org/book/ch15-05-interior-mutability.h...
A half-hour to learn Rust - https://news.ycombinator.com/item?id=25610741 - Jan 2021 (330 comments)
A half-hour to learn Rust - https://news.ycombinator.com/item?id=22448933 - Feb 2020 (148 comments)
I've been using other languages longer than 10 years too but not continuously enough to ever consider myself expert.
I'd say there are definitely rust experts out there, but I'd posit it's unlikely for the average dev to have gotten that far yet.
I think TFA is a great resource in terms of presenting syntax and idioms. My biggest problem with learning Rust though has been understanding how to do things when the borrow checker prohibits the solution that would be 'obvious' in C#, C++, etc. I started to make progress when I bought the O'Reilly Programming in Rust book, and then thoroughly read and re-read the chapter on memory management.
- in distrib: cargo, analyzer, clippy
- others: Aquascope godbolt intellij flowistry
__________________________
https://www.infoworld.com/article/3267624/whats-new-in-the-r...
I also chuckled at the "20 minute read".
fn tail<'a>(s: &'a [u8]) -> &'a [u8] {
&s[1..]
}
...
fn main() -> Result<(), std::str::Utf8Error> {
let s = std::str::from_utf8(&[240, 159, 141, 137])?;
println!("{}", s);
Ok(())
}
Sorry, `|::|&(_Rust!){}?`. I know you're sexy. But I'll prefer my eyesight and sanity over you.It does take a little while to get accustomed to, but the investment is more than worth it.
Can't comment on my sanity though.
One example:
> `let` patterns can be used as conditions in `if`:
Anyway, this tutorial looks great, I'll give Rust another go when I have a good project for it, but to me it seems there is a great need for a simpler language with similar memory management. Rust is just too complex, imho.
You can code without that, it's just that you are going to wish you had it after your first few programs.
> but the language itself seems needlessly complex to me
A lot of the complexity is around making the explicitness of the language bearable. If you had to be explicit without all the syntax sugar and type / lifetime inference it would be insufferable to program in.
See example from code I wrote this week: https://github.com/trane-project/trane/blob/master/src/data/...
Without the let, I'd have to do a match statement followed by an unwrap just to check if a field in an enum is set.
You... would not?
An `if let` trivially desugars to a `match`.
if let <pat> = <expr> {
...
}
becomes match <expr> {
<pat> => {
...
}
_ => {}
}Well, I have to agree Rust isn't one of the simplest PL-s on the planet. This is due to the fact that it is quite a modern PL and quite a versatile PL, supporting elements of functional programming, trait-oriented (conditional generics) programming, asynchronous programming, etc. and a capable standard library on top of it all. It takes, indeed, quite some time to take all of that Rust in. As a reward, you get a lot of expressiveness and the capability to discover a significant percentage (if not an overwhelming majority) of your programming mistakes at compile time as opposed to runtime (unit/integration tests or Q/A), which to me is priceless.
Nevertheless, from my experience, Rust is, at the same time, one of the most... "consistent", "predictable", "internally symmetric" PL-s I have ever seen. I consider Rust to be way easier to learn than, say, Swift.
> `let` patterns can be used as conditions in `if`
I somewhat cannot help it but feel that such an example should not be used in an introductory tutorial. `if let` is usually used to pattern-match a simple `enum`[1], not a complex `struct` that looks "dense" unless you're used to it.
Yes, exactly! Now can I have just a safe C without all the other stuff, pretty please? :) I understand Rust is not it, but I hope someone comes up with a simple PL which is also compile-time memory safe. I think it would be an instant hit.
> when I have a good project for it
... is a bad idea. I've heard this from several programmers who now use Rust professionally, but don't have first-hand experience about it. Their take can be boiled down to:
Rust has a learning curve that will mean that the first version will invariably be throw-away. Developing a mental model for how to change memory management structures to please the borrow checker and properly encode ownership seems like the biggest hurdle to writing good Rust.
I believe this is the main reason Rust adoption isn't skyrocketing, but still growing. The "onboarding" for Rust is more labor intensive and therefore disincentivizes its use.
Your example is a minor but quite useful piece of syntactic sugar, which was introduced a few years in following a similar construct being successful in Swift. You can read the entire reasoning at https://rust-lang.github.io/rfcs/0160-if-let.html
As an utter newbie to Rust, I can't guess whether or not the tutorial has become dated.