WHAT I DIDNT EXPECT THIS TO BLOW UP SO FAST. But as many have pointed out, no matter how confident I sound, I’m still a noob at c++ and rust. So pls take everything shown with a massive grain of salt. And pls go easy on the criticism 😢
Much of this reminds me of my experience learning rust. It was painful at times battling the borrow checker. But it has "unintentionally" taught me valuable lessons sometimes, how sometimes multiple mutable references can shoot you in the foot, or forcing me to take a deeper thought to what data types I'm working with. Sometimes though because of the borrow rules it's easy to take short cuts like cloning stuff willy nilly or unwrapping everything. But over time your intuition will develop to know immediately what will work well in a rust way. Welcome to the tribe :P Some things I love about the language: Enums (Every time I use another language I miss the way Rust Enums work), enforced naming convention(clean api's and for collaboration), excellent compiler error messages, Clippy (tool for giving you tips on improvements on your code)
4:40 i32 is a 32 bit integer that can be negative. u32 is a 32 bit integer that can't be negative, so unsigned integers are appropriate types for indexing. And usize is basically just a 32 or 64 bit unsigned integer, depending on whether or not your PC is 32 or 64 bit.
PS good video. It reminds me when I was younger and in a very similar stage, except Rust wasn't a thing at the time 😅. I went from Python - > C++ - > Rust as well. Something I will say is Rust basically forces you to learn concepts that C++ doesn't, but you can guarantee you'll shoot yourself in the foot if you don't understand them in C++. And good luck on your career 🙂
9:34 you don't actually need mutable references, as you don't change elements but only read them, so shared references will do. However you can even get two mutable references to elements in one vector using split_at_mut method
A "usize" is an unsigned integer with the size of the platform. Example: "usize" on a 64-bit CPU is an unsigned 64-bit integer. There is also "isize" which is the same but signed. Other non-dynamic number types in Rust are: u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 f32 f64 They are pretty self-explanatory, examples: u8 - Unsigned 8-bit integer. (AKA a byte.) f64 - 64-bit floating point number. i32 - Signed 32-bit integer. (Signed just means that it can also store negative numbers by giving up some of the larger unsigned numbers that it could store if it was unsigned.)
That's what I was thinking, too. ChatGPT is great for specific, hard-to-Google questions, but you should use it only as a way to orient yourself in the right direction, not try to have it do the work for you.
The borrow checker is actually quite simple. If you put something into a function call by value, it deallocates the variable after use. If you pass by reference, you can reuse the variable. And if you have something reading/writing to a variable, you cannot read/write to it somewhere else.
4:04 &str is a slice (a.k.a. fat pointer), which can point to any UTF8 string in memory, and it doesn't own the string to which it points. A String is an owned string. You can borrow it as a 4:08 &str to pass to functions, but you can also append to it, which may cause reallocation (like C++'s std::string).
something to note on your explanation at 3:32 - vectors and other containers are not automatically referenced when passed in cpp. this might also be a source of issues in your chess code. function parameters are ALWAYS passed by value (calling the copy constructor) and only referenced when you declare the type as a reference (const std::vector& myints). secondly i dont know what syntax you used for the cpp hashmap and linkedlist example at around the same time stamp - but those dont exist. not under those names anyway. a std::unordered_map is a hashmap-like container which also doesn't have the initialization syntax shown there. good work though i understand the beginners trouble with cpp - nice end montage lol
Ohhh I see. Yeah for the hashmap and linked list I was too lazy to find the actual syntax so I just put some BS there. There was supposed to be a comment at the start that said I was too lazy but I guess it got dropped out 🤷. Thx for the advice though!
great vid! dropped a sub! i suck at programming but that python ball collision checker code physically hurt me to look at :> very relatable and im sure youll go far! that chess montage was very fun
Nice video! When implementing a spatial hash in bevy you should store the Entity instead of a components reference, this enables you to get back the entities components inside your system using the spatial hash Resource.
In Python you can specify the variable type almost the exact same way as in Rust: a_number: int = 5 Not that it does much of anything aside from helping with documentation.
3:25 that doesn’t edit the outer vector because you are passing by value. You are just editing the local copy. You have to pass a mutable reference to do that. vector& n
I also did the python-to-rust switch for game development, it's been about 2 months and I love it, the typing is so much more explicit, I no longer lay awake at night fearing my integer is going to get turned into a float without my consent I suggest you try using bevy's event systems ASAP, they really change how you can make your systems interact, and they're a good way to handle mutating your components without conflict, I did mine like this: put player input event writers in pre-update, put all event readers in update, put game logic event writers in post-update, there's a ton of benefits to doing things this way that I won't get into in this comment, but it prevents systems mutating the same variable at the same time causing crashes, and guarantees that when systems are reading data, the data will not change during the frame, the data is essentially "still" while systems read it and decide how they want to change it my first components I wrote in bevy were Velocity, Acceleration, and Spin, it was a great study on how to work within the ECS
Cool video! I really encourage people to spend some time in a functional language, maybe Scala, if they come from an OOP background before diving into Rust. Everything will make sense and you'll pick it up much faster.
String is a data object internally represented as a Vec and is far more versatile. &str is a pointer to a string literal. They are much less flexible but faster. &String and str are almost never used. usize is an unsigned number the size of the systems pointer length.
to add ontop of that, string literals are &str and not String because Rust removes duplicate string literals, so you get a shared immutable reference this is an optimization done at compile time
4:50 if you have a variable named "index" it should almost always be a usize by default, e.g. `let index: usize = 0;` or `let index = 0usize;` usize is just the largest integer the local system can handle... it prevents a 32 bit system from trying to store a 64 bit integer
2:44 BASED opinion. everybody hates on Rust syntax for some reason, but its so beautiful (or maybe I've been indoctrinated by the new testament, aka the rust programming language 2nd edition, and I am now too far gone. or maybe rust is just better ¯\(ツ)/¯ )
@@arjix8738 maybe... Tbh, i like the syntax where the type is on the right after the colon. it looks cleaner. I've also heard complaints about forming a string, where people complain that you have to use "String::from()" or "String::new()", but obviously they don't understand the beauty of Rust strings
10:40 You might try saving detected collisions to a list of collision events containing data about which balls to update and how to update them. Then you update one ball at a time using that data instead of copying the whole ball list.
&str vs String in a nutshell: &str is a 'String' which you know how long it is, but don't know if you can write past the last byte of the &str. A String is also a 'String' which you know how long it is, but also have an extra field which we call capacity which lets you know how much more can you write to it
10:30 Instead of copying the list of balls every time you want to check collisions, Why not use immutable references in your for loops and push the collision updates to a stack? Then after you've looped through each ball, you have a vector of the collision updates that need to be performed and can do all of them without needing 2 mutable references or having only half the balls have collision.
I'm actually amazed you got this far... Bevy uses high level Rust concepts, that can do amazing stuff when utilized correctly. But hell I'm tinkering with Rust now almost two years and I still do not feel comfortable enough to play around with bevy beyond its examples. Learning Rust is already hard mode, learning Rust with Bevy earns you respect from the Doom Slayer...
A minor correction, there is no such a thing as a reference in Rust. At least not in the way you think of it from other languages. When you pass a parameter to a function you either let it borrow the value (meaning you want to keep control over it after the function call) or you give the function ownership of the value. Borrowing is not equivalent with pass by reference and give ownership is not equivalent with pass by value. Realizing this and accepting it is the key to truly unlocking the awesomeness of Rust.
7:55 that pub let mut is not valid rust, global variables are declared with static pub static mut SCORE: i32 = 0; you can add `mut` to make it mutable, however accessing it is unsafe because if you access it from different threads you'll end up with undefined behavior (possibly data races and memory corruption). You can use a AtomicI32 instead, which uses internal mutability which means the static variable itself is not mutable but the value inside the AtomicI32 is and it is safe to access on multiple threads at the same time because the CPU synchronizes the access to that memory location between all CPU cores. pub static SCORE: AtomicI32 = AtomicI32::new(0);
@@coffee-is-power yeah I noticed this right after I did the snippet… didn’t think anyone would notice the error though. Statics and constants in rust are a pain…
Your explanation about C++ references doesn't seem right to me. C++ Vectors aren't implicitly copied by reference and there is also a difference between a const and a mutable reference. References in C++ is just a convenient way to pass around a pointer that is known to be initialised, so technically you can also pass a reference using a pointer where you can pass a pointer to a constant. I have included some examples below for you: // Pass by value. void foo(std::vector vec) { //... } // Pass by mutable reference. void foo(std::vector& vec) { // ... } // Pass by mutable reference using pointer. void foo(std::vector* vec) { // ... } // Pass by const reference. void foo(const std::vector& vec) { // ... } // Pass by const reference using pointer. void foo(const std::vector* vec) { // ... } Passing by reference using pointers can also be confusing but a great explanation is from a Stackoverflow post describing: """ const char* is a pointer to a constant char char const* is a pointer to a constant char char* const is a constant pointer to a (mutable) char """ (source: stackoverflow.com/questions/162480/const-int-vs-int-const-as-function-parameters-in-c-and-c)
Please, don't fake your knowledge of c++. Pretty much any c++ snipped in the video is incorrect. Vectors, like any other type, get copied when passed as value Your second code snipped after the vector snipped was just a python reskin that doesn't have anything to do with c++ Your expression with .copy could be inlined, you don't even need to copy it when passing it as value since it is copied there, unless you've not propperly implemented the constructor. Btw at 5:45 println! already flushes, only print! doesn't.
Ok gotchu. Yeah I’m still learning the inner workings of C++ and rust so I’m still kinda blur on it. I’ll make sure to fact check next time though, I didn’t expect this to get that many views lol
@@cheesepop7175 You must be a beginner in compsci to think that. The terminal is the MOST powerful tool for a person working with a computer, no doubt about it. Not everything needs to be a GUI designed for babies.
WHAT I DIDNT EXPECT THIS TO BLOW UP SO FAST.
But as many have pointed out, no matter how confident I sound, I’m still a noob at c++ and rust. So pls take everything shown with a massive grain of salt. And pls go easy on the criticism 😢
noob
@@TheSandwichCoder then get good first before spreading misinformation
@@TheSandwichCoder at least have the decency to run the code and check if it does what you expect it to do.
Damn chill
yea, lost me at words python + rust as c++ dev. anyway, great video, there is always a lot to be lerned.
Much of this reminds me of my experience learning rust.
It was painful at times battling the borrow checker.
But it has "unintentionally" taught me valuable lessons sometimes, how sometimes multiple mutable references can shoot you in the foot,
or forcing me to take a deeper thought to what data types I'm working with.
Sometimes though because of the borrow rules it's easy to take short cuts like cloning stuff willy nilly or unwrapping everything.
But over time your intuition will develop to know immediately what will work well in a rust way.
Welcome to the tribe :P
Some things I love about the language:
Enums (Every time I use another language I miss the way Rust Enums work), enforced naming convention(clean api's and for collaboration), excellent compiler error messages, Clippy (tool for giving you tips on improvements on your code)
TanTan! ;) can't wait for the next video to drop my friend.
whatever you're doing keep it up psst yes im subbed to you!
WTF MOM GET THE CAMERA 📷
this shit is hella well made for 69 subs
I thought he had a lot more, video is good quality
nice
4:40 i32 is a 32 bit integer that can be negative. u32 is a 32 bit integer that can't be negative, so unsigned integers are appropriate types for indexing. And usize is basically just a 32 or 64 bit unsigned integer, depending on whether or not your PC is 32 or 64 bit.
PS good video. It reminds me when I was younger and in a very similar stage, except Rust wasn't a thing at the time 😅. I went from Python - > C++ - > Rust as well. Something I will say is Rust basically forces you to learn concepts that C++ doesn't, but you can guarantee you'll shoot yourself in the foot if you don't understand them in C++. And good luck on your career 🙂
9:34 you don't actually need mutable references, as you don't change elements but only read them, so shared references will do. However you can even get two mutable references to elements in one vector using split_at_mut method
A "usize" is an unsigned integer with the size of the platform. Example: "usize" on a 64-bit CPU is an unsigned 64-bit integer. There is also "isize" which is the same but signed.
Other non-dynamic number types in Rust are:
u8
i8
u16
i16
u32
i32
u64
i64
u128
i128
f32
f64
They are pretty self-explanatory, examples:
u8 - Unsigned 8-bit integer. (AKA a byte.)
f64 - 64-bit floating point number.
i32 - Signed 32-bit integer. (Signed just means that it can also store negative numbers by giving up some of the larger unsigned numbers that it could store if it was unsigned.)
And that’s how summer works as a guy! 😂
Memes aside - welcome to oxidation, and a phenomenal video btw
6:43 bro complains about having to read documentation, what a world we live in
That's what I was thinking, too. ChatGPT is great for specific, hard-to-Google questions, but you should use it only as a way to orient yourself in the right direction, not try to have it do the work for you.
The borrow checker is actually quite simple. If you put something into a function call by value, it deallocates the variable after use. If you pass by reference, you can reuse the variable. And if you have something reading/writing to a variable, you cannot read/write to it somewhere else.
Awesome video. Peak cinema. You'll have one billion subs in no time
4:04 &str is a slice (a.k.a. fat pointer), which can point to any UTF8 string in memory, and it doesn't own the string to which it points. A String is an owned string. You can borrow it as a 4:08 &str to pass to functions, but you can also append to it, which may cause reallocation (like C++'s std::string).
1:16 jdh enjoyer spotted
Also great video, as a Rust and Bevy evangelical i approve
something to note on your explanation at 3:32 - vectors and other containers are not automatically referenced when passed in cpp. this might also be a source of issues in your chess code. function parameters are ALWAYS passed by value (calling the copy constructor) and only referenced when you declare the type as a reference (const std::vector& myints). secondly i dont know what syntax you used for the cpp hashmap and linkedlist example at around the same time stamp - but those dont exist. not under those names anyway. a std::unordered_map is a hashmap-like container which also doesn't have the initialization syntax shown there.
good work though i understand the beginners trouble with cpp - nice end montage lol
Ohhh I see. Yeah for the hashmap and linked list I was too lazy to find the actual syntax so I just put some BS there. There was supposed to be a comment at the start that said I was too lazy but I guess it got dropped out 🤷. Thx for the advice though!
np man keep up the good work
great vid! dropped a sub! i suck at programming but that python ball collision checker code physically hurt me to look at :>
very relatable and im sure youll go far! that chess montage was very fun
I also learned rust from a chess engine project, it's quite well suited for it
Yeah it helps a lot to learn the logic and basic functions 😎😎
4:43 A usize is an unsigned integer that is the same size as a CPU register, and is used for offsets and lengths.
Very well made video, Nice 👍👍
Nice video! When implementing a spatial hash in bevy you should store the Entity instead of a components reference, this enables you to get back the entities components inside your system using the spatial hash Resource.
In Python you can specify the variable type almost the exact same way as in Rust:
a_number: int = 5
Not that it does much of anything aside from helping with documentation.
3:25 that doesn’t edit the outer vector because you are passing by value. You are just editing the local copy.
You have to pass a mutable reference to do that.
vector& n
75 subs? Let me fix that.
Keep up the good work
this is so cool
i wish i could edit like that xd
youre the sigma sandwichcoder thank you for the good content
I also did the python-to-rust switch for game development, it's been about 2 months and I love it, the typing is so much more explicit, I no longer lay awake at night fearing my integer is going to get turned into a float without my consent
I suggest you try using bevy's event systems ASAP, they really change how you can make your systems interact, and they're a good way to handle mutating your components without conflict, I did mine like this: put player input event writers in pre-update, put all event readers in update, put game logic event writers in post-update, there's a ton of benefits to doing things this way that I won't get into in this comment, but it prevents systems mutating the same variable at the same time causing crashes, and guarantees that when systems are reading data, the data will not change during the frame, the data is essentially "still" while systems read it and decide how they want to change it
my first components I wrote in bevy were Velocity, Acceleration, and Spin, it was a great study on how to work within the ECS
Cool video! I really encourage people to spend some time in a functional language, maybe Scala, if they come from an OOP background before diving into Rust. Everything will make sense and you'll pick it up much faster.
String is a data object internally represented as a Vec and is far more versatile.
&str is a pointer to a string literal. They are much less flexible but faster.
&String and str are almost never used.
usize is an unsigned number the size of the systems pointer length.
to add ontop of that, string literals are &str and not String because Rust removes duplicate string literals, so you get a shared immutable reference
this is an optimization done at compile time
4:50 if you have a variable named "index" it should almost always be a usize by default, e.g. `let index: usize = 0;` or `let index = 0usize;`
usize is just the largest integer the local system can handle... it prevents a 32 bit system from trying to store a 64 bit integer
2:44 BASED opinion. everybody hates on Rust syntax for some reason, but its so beautiful (or maybe I've been indoctrinated by the new testament, aka the rust programming language 2nd edition, and I am now too far gone. or maybe rust is just better ¯\(ツ)/¯ )
@@_ethqnol_ I have converted to be a rustacean
I think most people "hate" it because it looks like typescript and other languages that have the type on the right
@@arjix8738 maybe... Tbh, i like the syntax where the type is on the right after the colon. it looks cleaner. I've also heard complaints about forming a string, where people complain that you have to use "String::from()" or "String::new()", but obviously they don't understand the beauty of Rust strings
10:40 You might try saving detected collisions to a list of collision events containing data about which balls to update and how to update them. Then you update one ball at a time using that data instead of copying the whole ball list.
this video is extemely well made i susbroobed
1:26 Damn, I'm honored lol
Yeah just ignore the one below it 😂
@@TheSandwichCoderthick of it 😱
really cool video man, keep it up
&str vs String in a nutshell:
&str is a 'String' which you know how long it is, but don't know if you can write past the last byte of the &str.
A String is also a 'String' which you know how long it is, but also have an extra field which we call capacity which lets you know how much more can you write to it
peak cinema
You're great!
Honestly, amazing. Do you have a Discord server?
10:30 Instead of copying the list of balls every time you want to check collisions, Why not use immutable references in your for loops and push the collision updates to a stack? Then after you've looped through each ball, you have a vector of the collision updates that need to be performed and can do all of them without needing 2 mutable references or having only half the balls have collision.
4 nested for loops is crazy
I'm actually amazed you got this far...
Bevy uses high level Rust concepts, that can do amazing stuff when utilized correctly.
But hell I'm tinkering with Rust now almost two years and I still do not feel comfortable enough to play around with bevy beyond its examples.
Learning Rust is already hard mode, learning Rust with Bevy earns you respect from the Doom Slayer...
14:50 rust is actually llvm-based so....
also, did you compile it in release mode? you get much better performance in release mode vs debug mode
this video earned my approval
btw im stupid yippee
1:26 "Goofy dies in a car crash while listening to sunflower " 💀💀💀💀
awesome video, the music and sound effects are just WAY too loud
this burns my eyes
Nice video man. Thumbnail would've been way better using a white background and red and black text
nice vid keep it up
A minor correction, there is no such a thing as a reference in Rust. At least not in the way you think of it from other languages. When you pass a parameter to a function you either let it borrow the value (meaning you want to keep control over it after the function call) or you give the function ownership of the value. Borrowing is not equivalent with pass by reference and give ownership is not equivalent with pass by value. Realizing this and accepting it is the key to truly unlocking the awesomeness of Rust.
Ohhh yeah I heard those terms before but I didn’t really get what they meant. Thx though!
6:12 There are faster linkers, like gold, and you can setup Bevy to be made a DLL while developing.
Time to try Nim if you want something Python-ish or Odin if you want something C-ish.
I believe you could use an Arc to view the balls instead of making a snapshot
3:20 this is completely wrong. Variables in C++ are always passed by value unless the parameter’s type is a reference
Helo Mr. im new here. good video. 👍
I love how challenging it is. I feel like an idiot every time I use Rust, but I keep going because of my ego. Lmao
Too late for Rust man! Imagine Python but fast... They even call it Mojo!
just use pypy at that point
00:33
Wait whatttt's in your browser thooo😂😂
7:55 that pub let mut is not valid rust, global variables are declared with static
pub static mut SCORE: i32 = 0;
you can add `mut` to make it mutable, however accessing it is unsafe because if you access it from different threads you'll end up with undefined behavior (possibly data races and memory corruption). You can use a AtomicI32 instead, which uses internal mutability which means the static variable itself is not mutable but the value inside the AtomicI32 is and it is safe to access on multiple threads at the same time because the CPU synchronizes the access to that memory location between all CPU cores.
pub static SCORE: AtomicI32 = AtomicI32::new(0);
@@coffee-is-power yeah I noticed this right after I did the snippet… didn’t think anyone would notice the error though. Statics and constants in rust are a pain…
YOU ONLY HAVE 189 SUBS?
I love low chatgpt is insulting you. i'm glad he doesn't insult me. i use him 24/7 to write html and css.
hmm, I think I stick with C++ and risk the stability of the universe, because why not ¯\_(ツ)_/¯
13:59 after seeing those comments why do i feel like it was written by chatGpt 🤔🤔🤔🤔
Your explanation about C++ references doesn't seem right to me. C++ Vectors aren't implicitly copied by reference and there is also a difference between a const and a mutable reference.
References in C++ is just a convenient way to pass around a pointer that is known to be initialised, so technically you can also pass a reference using a pointer where you can pass a pointer to a constant. I have included some examples below for you:
// Pass by value.
void foo(std::vector vec) {
//...
}
// Pass by mutable reference.
void foo(std::vector& vec) {
// ...
}
// Pass by mutable reference using pointer.
void foo(std::vector* vec) {
// ...
}
// Pass by const reference.
void foo(const std::vector& vec) {
// ...
}
// Pass by const reference using pointer.
void foo(const std::vector* vec) {
// ...
}
Passing by reference using pointers can also be confusing but a great explanation is from a Stackoverflow post describing:
"""
const char* is a pointer to a constant char
char const* is a pointer to a constant char
char* const is a constant pointer to a (mutable) char
"""
(source: stackoverflow.com/questions/162480/const-int-vs-int-const-as-function-parameters-in-c-and-c)
What is Hello Wolrd
The best program ever
the wordle code is bruh ._.
skill issue is not python or rust , skill issue is gaming operating system with browser based notepad++ clone
bro uses onedrive
Bro really said
if n == 0:
return 0
if n == 1:
return 1
instead of
if n < 2:
return n
You meant explicit not readable
So you're asian? Name every asian person
281 subs? wtf?
I mean you could've cached the python script at the start of the video...problem solved...
You know that coding in rust on windows is illegal, right?
now learn zig
vscode and windows nah you need neovim and linux
vscode is fine, windows though is 💀
The day I switch to neovim is the day I get a gf 😂 (so never)
i dont really get the point of neovim, i only use it to quickly edit text files from the terminal, but configuring it seems like a hassle
kakoune >>>>>>>
Please, don't fake your knowledge of c++. Pretty much any c++ snipped in the video is incorrect.
Vectors, like any other type, get copied when passed as value
Your second code snipped after the vector snipped was just a python reskin that doesn't have anything to do with c++
Your expression with .copy could be inlined, you don't even need to copy it when passing it as value since it is copied there, unless you've not propperly implemented the constructor.
Btw at 5:45
println! already flushes, only print! doesn't.
Ok gotchu. Yeah I’m still learning the inner workings of C++ and rust so I’m still kinda blur on it. I’ll make sure to fact check next time though, I didn’t expect this to get that many views lol
can't wait for this language to die soon so everyone can shut up about it and return to normal languages like c and c++
I'm jealous
x d
1:55 is he actually using command line? dude, it's not the 80s, people use GUIs now.
This better be a joke
@@aarorissanen930 I mean it's really primitive
@@cheesepop7175 You must be a beginner in compsci to think that. The terminal is the MOST powerful tool for a person working with a computer, no doubt about it. Not everything needs to be a GUI designed for babies.
3:56 bro tryna do recursive with this one 🫡🫡🫡