Dude, I think your channel is amazing, I can't believe people still deal with the same memory errors on C and C++, it's time to switch to an actual modern language. And I'm glad that people like you are making this community one of the best among the programming languages.
Wo wo wo, hold your horses, No doubt Mr. Bogdan is one of his kind and I admire his contribution, but chances are the operating system that you watching and commenting here is implemented somehow in its core with C and C++, sooner or later Linus Torvalds will implement Rust into one of his upcoming kernels
I really like the way you explain concepts of Rust. I have been reading several books on Rust and enrolled for courses on the same but I find your explanations being concise and well delivered. I rate you videos on learning Rust at 9/10. I have only two criticisms 1) Fast forwarding sections of the video where you type, I think it is okay for us to follow you type at natural speed as it takes time to absorb and process the information taught. I find myself having to pause or even rewind to better understand these sections. 2) The background music, I think background music in educational videos cause some distraction. The inclusion of background music seems to be a common trend on RUclips videos, but I would be had pressed to see a college class being taught as music plays in the background. The background music in your videos seems to oscillate in volume with a frequency of 1 Hertz. From the comments, it seems I am the only one finding these two challenges. Probably this requires more investigation. Perhaps someone with training and experience in education and learning can provide their input on this matter.
Thank you for the feedback! I agree that natural typing is better for learning. Similar to professors writing on the chalk board, it gives time to process the information. I will improve this aspect of my videos in the future. The background music should be improved in later videos although I didn't remove it altogether. That's something I will consider doing.
@@letsgetrusty I don't have issue with speeding up typing, but when deleting and writing new code to do the same (or similar), as around 3:00, it would be better to comment out the old code, write the new code, and only then delete the commented out code. So we can compare codes, and see that these codes do the same thing.
Wow dude, been using a book to learn Rust and each chapter was just bloat of unnecessarily complicated examples. You explanation is just spot on! Please continue updating the playlist, even after The Rust Lang Book is done. Maybe a code-along with a webapp or a terminal utility.
11:27 Couldn't you have used a normal if-statement in this case? You can always compare against a specific value like _Some(3),_ the "if let" syntax only comes in handy when you want to catch any _Some(_)_ or want to reuse the inner value that you're comparing against, for example: if let Some(value) = some_value { println!("The value is {}", value); }
Thank you for this comment. I immediately tested if some_value == Some(3) { ... } while following along with this and found it worked just fine, so I was wondering what the purpose of "if let" could be. Your explanation clarified it for me instantly.
Thank you. I was thinking something similar and this clears it up well for me. This is a tool I've been looking for in a typed language for a while now. It seems like I shouldn't have delayed learning rust so long.
Yeah the example wasn't clear this time, the book showed a better example. if-let is used for pattern matching, not for value matching, in that case, an if would be just fine.
11:30 tested, it works, but is confusing, and I still don't know any case where you would specifically need that syntax, but this also works: if Some(3) == some_value { /* do something */ }
It was a pretty bad example. `if let` is mainly useful for when you have an enum that holds some inner value in some variant, and you want to access the inner value on _that specific_ variant. For instance: enum MyEnum { A(i32), B(u32) } let my_enum = MyEnum::A(0i32); if let A(inner_value) = my_enum { println!("my_enum is the A variant with {} as the inner value", inner_value); } A similar thing is `let else` which lets you _bind_ the inner value of some variant to a variable, or run some other code if the enum is _not_ that variant, like so: enum MyEnum { A(i32), B(u32) } let my_enum = MyEnum::A(0i32); let MyEnum::A(inner_value) = my_enum else { panic!("my_enum is the B variant, need the A variant"); }
For the if let syntax, it also reduces the amount of identantion used, e.g: match some_val { Some(val) => { use(val); }, _ => (), } if let Some(val) = some_val { use(val); }
Great videos! You explain the concepts really well. Minor thing I recognized: I think you forgot the '&self' as an argument for the method 'fn some_function' at 4:14.
nah, he just created an associative function, but honestly his explanation of impl assumes you know about structs, and wasn't very cohesive. Not to mention he didn't really explain very well how to access pieces of information from enums. I like most of this guy's videos, but this one didn't hit the mark at all.
I've seen syntax similar to 'if let' in other languages. It makes heaps more sense if you consider an example of a bound variable: if let Some(x) = some_value { ... } You're conditionally defining "let x" to be the bound value within the following code block if it matches the specified variant.
3:33 - That's not an anonymous struct, since there's no anonymous structs in Rust. In the Rust Book it's described as "has named fields like a struct does" and in the example it's commented as "c-like structures".
I agree with your thoughts about if let syntax: It is confusing, especially if you look at the "if let" examples mixed with else, else if let, combinations in the book. I bet an Effective Rust book would contain an item "Don't use if let, use match instead.
if let is very useful (succinct) if you use it correctly. if let Some(item) = vector.get(20) { // or any Option returned by a function // do something with item } That's what if let is for.
The `if let` syntax is confusing to me too, but I think I'm finally starting to get it after I realized that my problem was actually that I didn't understand what `let` means well enough. I thought it just bound the LHS to the RHS, but it's more powerful than that. Conceptually, `let` just fills in the blanks on the left of the `=` to make the left and right sides of the `=` match. So `let x = 3;` is filling in the "blank" (in this case `x`) with a `3` to make the equality hold. More complicated is `let Some(x) = Some(3);` but in this case `x` gets bound to `3` as well. The `if let Some(x) = optional_function()` is true if `let` can do its job of filling in the "blank" `x`. If `optional_function()` doesn't return something of the form `Some(y)`, then `let` fails; otherwise, `x` gets bound to `y` and we can do stuff with `x`. This article really helped me understand it better: h2co3.github.io/pattern/.
8:40 if I use println!("{ }",value...) , the number"25" would be printed out, but if I type the value(....) function directly like you did in the video , the numbe"25" wont be printed out like your example, so everytime I need to add println!("{ }", value ..) in order to print out the number as well ? and Why the number wont be printed out if I directly type the value(...) function ? Thank you for your video !
In my example the state is printed out, not the value, and I use the println!("{ }", state) syntax. This syntax is required because the first argument must be a string literal.
Wow, it's interesting that you explain a lot of complex concepts very simply, but you find "if let" confusing. Personally, it's my favorite pattern matching feature, and I think there's a simple way to look at it. It's just a pattern matching (if) + descructuring (let). In your example you don't use destructuring, which is probably why it seems confusing: if let Some(3) = ... But if you consider an example where you need some heavy duty destructuring, it starts making a lot of sense: if let Some(Connection(Status("OK"), IpAddr(ip), Port(port))) = wait_connection() { println!("Connected to {ip}:{port}") } obs: The Connection struct is far from optimal, but it gets the point accross.
In 9:50, its posible to do the same func but instead of taking a i32 takes a ? I did this but didn't work fn _plus_one(x: Option) -> Option { match x { Some(i: i32) => Some(i + 1), _ => None, } }
11:27 It seems like the syntax is basically a simple if condition with a variable assignment embedded into it, declaring that variable to only be within the scope of the if block and making an assumption on the value of the variable which is guaranteed by the if check. It's doing two things at once and the one depends on the other (hence it can't be in a separate statement). I'm not sure of a better syntax of the top of my head, though when I first saw that just now I'll admit I was a bit baffled by its syntax.
I looked up another example where they actually used the number inside the option enum, `if let Some(i) = some_value`, which made it much better. I haven't written a line of code in the language yet, but it seems like you shouldn't need an if-let expression if you are doing an exact match. Then a simple equality check ought to work (right? Yeah, I should have read some more comments before I made my own).
Using match statement to calculate coin value seems to be overkill. Is there a way to keep coin value inside enum? Like in C/C++ we write enum { nikel = 1, dime = 10 ... }
Yes. An easy example is a token within an AST. An AST can have possibly dozens of types of tokens, but you may want to abstractly refer to any one of those types as _just_ an abstract token. In other languages you may model this with a class hierarchy via inheritance, whereas in Rust you may model this with an enum where each variant is a type of token. One variant is a '>' token, another variant is a '>>' token, and a third can be a generic character token to support identifier characters (ie A-z, 0-9 and _). The '>' and '>>' tokens don't need to store any inner values since you have enough information from the variant alone ('>' is a single >, '>>' is two >'s in a row), but the generic character token needs to store the specific character code of the token, so you'd have that variant store an inner char.
Yes. Those are type hints and are driven by type inference, since Rust and the IDE are both smart enough to figure out what the type is based on what functions are used and where the value originates from.
Why can't we iterated over each of the variants of an enum ? Seems like such an obvious and convenient thing to want to do. Or does it mean I am thinking about and possible using enums in the wrong way ?
You probably are. It doesn't make any sense to iterate over the variants of an enum, as the variants themselves aren't useful. Enums are used to describe types that can take multiple forms, and each variant describes a particular form that the type can be (think an abstract token within a code parser, where each individual type of token is a separate variant). When you construct an instance of the type, you are constructing an instance of _a specific form_ of that type, which you do by selecting _a specific variant._ As such it doesn't make any sense to iterate over the variants of an enum here, either, as you'd basically be taking an instance of a type that is in one form (say Some(T) for an Option) and trying to force it to be another form (say None for that same Option). The instance of that type is in that specific form for a reason, so trying to force it to be another form is problematic and has a very real chance of breaking things (especially if the type is storing any inner data).
Something I don't understand about the examples in this chapter is why wouldn't you just say "let five = 5)" then do "let six = plus_one(five)". is there some reason you would want to use Some(5) there?
Good to know that it's not just me that is confused about if let. Match statements are so much more readable. You don't really declare anything new even though you are using the let key word, and just like the match, whatever is in the Some() is scoped. I almost want to go back to Typescript now.
You are declaring something new, the example in the video was just bad. If-let checks the variant of the enum, destructures the enum if it's of the specified variant (ie Some(T) for Option), then binds the inner value of the variant to the variable name within the variant's paranthesis within the scope of the if-let block. The "let" signifies that you're going to be destructuring the enum and binding the inner value to a new variable. Say you had the below function: fn main() { let my_string: Option = Some(String::from("Hello, World!")); } And you wanted to do print the String behind the Option, _if_ there is a String behind the Option. To do so, you'd do this: fn main() { let my_string: Option = Some(String::from("Hello, World!")); if let Some(the_inner_string) = my_string { println!("The string is: {}", the_inner_string); } } It's basically a shortcut for the below match statement: fn main() { let my_string: Option = Some(String::from("Hello, World!")); match my_string { Some(the_inner_string) => println!("The string is: {}", the_inner_string), None => {} } } The match statement has an unnecessary branch to cover the None variant, so if-let lets you get rid of that and _only_ use the Some variant.
It was a bad example. The key point is that if-let lets you bind the inner value of the enum variant to a variable that's scoped to the if-let block, letting you safely access that inner value within the if-let block, since you've already checked that the variant is correct.
With enums they kinda confuse me when you have enum IpAddrKind{ V4, V6 } then you create instances of these enum types what does that actually do? let four: IpAddrKind=IpAddrKind::V4; like what does ^^ even mean really? what can I do with that info. Great video btw I just find this topic confusing for some reason.
Internally, Rust uses a special tag to differentiate between the variants of each enum. Basically, imagine if it looked like this: enum IpAddrKind { V4, // tag = 0 V6 // tag = 1 } When you do this: let four = IpAddrKind::V4; What you're doing is constructing a value that holds the tag of the variant you've selected, sort of like so: let four = /* IpAddrKind { tag: 0 } */; When you do this later on in the code: match four { IpAddrKind::V4 => /* something */, IpAddrKind::V6 => /* another thing */, } Rust emits code equivalent to: if /* four.tag */ == 0 { /* something */ } else if /* four.tag */ == 1 { /* another thing */ } To choose which branch to execute based on the tag. Enums that store data within each variant work the exact same, but also place the data alongside the tag, choosing a specific order based on which is smaller between the tag and the data, since Rust can change the order to potentially reduce the size of the whole enum type. Essentially, this is what it'd look like: enum IpAddrKind { V4(u8, u8, u8, u8), // tag = 0, memory layout = { u8, u8, u8, u8, tag } V6(String) // tag = 1, memory layout = { String, tag } } In the above code the quadruplet of u8's and the String occupies the same space in the enum type's memory layout, as Rust knows that you will only use _either_ the quadruplet of u8's _or_ the String _and never both at the same time,_ letting it safely reuse that space to reduce the size of the enum type (look up unions in C, Rust treats the per-variant data as a union). Because Rust has the tag, it can know what variant you're using and is able to safely let you access the per-variant data, like so: match four { IpAddrKind::V4(a, b, c, d) => /* something that uses a, b, c and d */, IpAddrKind::V6(s) => /* another thing that uses s */ }
Is a good developer doesn’t use strings for an IP address but just an u64 that’ll cover the IPv4 32 bit addresses and the IPv6 64 but addresses ;) In the socket layer they are actual 32/64 addresses :) But I catch your point. Great demo.
Plain if statement seems to work just like if let. So why if let should/must be used instead? if some_value == Some(3) { println!("{:?}", some_value); }
The example in the video was bad. If-let is used for when you don't know what the enum variant contains (ie you don't know that it's Some(3)), but you want to access it and you know it has to be of a specific variant (ie Some(n), where n is the number you want to access). If-let basically binds the inner data of the enum variant to a local variable, letting you access it through that variable, like so: if let Some(n) = some_value { println!("{} + 10 = {}", n, n + 10); }
Very confusing. Even after googling I don't understand why they chose this syntax. `if let` is pattern matching, so in a sense ìf let` is to `match` what `if` is to `switch`. Except that rust merges match and switch into the same statement, making this even more confusing.
i agree that it's weird, but assignment makes sense because it also binds the pattern identifier if let Some(val) = func() binds `val` to the value inside Some(_) but does nothing if it is None, unless you have an else clause same deal with while let
At the rate this is going I'm frankly terrified at the concept of there being 44 videos. If this was C++ (which I'm fluent in) at this rate I'd expect maybe 20 videos.
I'm still so confused by enums existing as a concept... I mean it's just a "legal" hardcode. Hardcode = bad code, enums != bad code. I don't get it, please someone explain this. I'm 1,5 in programing(C, JS, Python), almost a year of commertial expirience, and I've never used an enums. Literally. Why they are so functional in Rust? It really doesn't make any sence to me
What do you mean by hardcode? The awesome thing with Rust enums is that they're _not_ hard coded, they can accept and store variable values that originate from runtime code, in a way that lets you determine _what_ group of values the enum is currently storing. It's as if you took a union in C, added a tag that told you what variant the union is currently in, then sculpted the language around using that tag to make certain guarantees around the variant that the union is in when it's used in different contexts (pattern matching, if-let destructuring, let-else destructuring, etc). Take any usecase for a C union, add a ton of extra safety features on top that made it safer to use, then imagine the new usecases that would open up if you had that extra safety, and that's why they're so functional in Rust.
Convert a go developer? Oh shit, not another sw eng rivalry :P that's it, in the great tradition of evil emacs, I'm going to wrap all my Go up in Rust calls, and vice-a-versa.
Yep. It’s almost word-for-word and example-for-example. I will admit, however, getting fed the chapter in 12.5 minutes is a lot faster than reading it myself. But that’s just for seeing the syntax. The diagrams showing the flow of data within memory is (imo) extremely important for understanding HOW rust works, which you don’t get in videos like these.
📝 Get your *FREE Rust cheat sheet* : www.letsgetrusty.com/cheatsheet
go developer here. Had to comment when I heard your little intro. Gotta say I'm loving rust. Already subscribed. Thanks for the awesome tutorial.
Dude, I think your channel is amazing, I can't believe people still deal with the same memory errors on C and C++, it's time to switch to an actual modern language. And I'm glad that people like you are making this community one of the best among the programming languages.
Appreciate the support Thiago!
Wo wo wo, hold your horses, No doubt Mr. Bogdan is one of his kind and I admire his contribution, but chances are the operating system that you watching and commenting here is implemented somehow in its core with C and C++, sooner or later Linus Torvalds will implement Rust into one of his upcoming kernels
@@MohammedYasinRashidI do believe that’s since been done no? 😅
With every subscription you convert a Go dev. xD
I really like the way you explain concepts of Rust. I have been reading several books on Rust and enrolled for courses on the same but I find your explanations being concise and well delivered. I rate you videos on learning Rust at 9/10.
I have only two criticisms
1) Fast forwarding sections of the video where you type, I think it is okay for us to follow you type at natural speed as it takes time to absorb and process the information taught. I find myself having to pause or even rewind to better understand these sections.
2) The background music, I think background music in educational videos cause some distraction. The inclusion of background music seems to be a common trend on RUclips videos, but I would be had pressed to see a college class being taught as music plays in the background. The background music in your videos seems to oscillate in volume with a frequency of 1 Hertz.
From the comments, it seems I am the only one finding these two challenges. Probably this requires more investigation. Perhaps someone with training and experience in education and learning can provide their input on this matter.
Thank you for the feedback!
I agree that natural typing is better for learning. Similar to professors writing on the chalk board, it gives time to process the information. I will improve this aspect of my videos in the future.
The background music should be improved in later videos although I didn't remove it altogether. That's something I will consider doing.
None of those aspects bother me. Perhaps, I just got used to coding having earphones on (with doom eternal soundtrack being played).
I haven't found it to be an issue either, but maybe experiment-do a video two ways and see what people like?
@@letsgetrusty Yes, please remove the background music.
@@letsgetrusty I don't have issue with speeding up typing, but when deleting and writing new code to do the same (or similar), as around 3:00, it would be better to comment out the old code, write the new code, and only then delete the commented out code. So we can compare codes, and see that these codes do the same thing.
Wow dude, been using a book to learn Rust and each chapter was just bloat of unnecessarily complicated examples. You explanation is just spot on! Please continue updating the playlist, even after The Rust Lang Book is done. Maybe a code-along with a webapp or a terminal utility.
books are the most inefficient method for learning, as you say, absolutely bloated, they have pages to fill, its a pre 21st century learning tool
@@theLowestPointInMyLifedude meant the official rust documentation books which are not books
@@theLowestPointInMyLife Books are supposed to cover everything. It's not the author's fault if the reader is inadept at skimming the book.
Rust's enum are so amazing! My c++ mind is blown.
This channel is amazing, you explained and digested such a complex language well, thank you
Your "convert a go developer" comment is priceless. I do love go...but as I learn more rust, I see less of a need/desire to use it.
11:27 Couldn't you have used a normal if-statement in this case?
You can always compare against a specific value like _Some(3),_ the "if let" syntax only comes in handy when you want to catch any _Some(_)_ or want to reuse the inner value that you're comparing against, for example:
if let Some(value) = some_value {
println!("The value is {}", value);
}
Otherwise the content of that video was summed up really well, thank you
Thank you for this comment. I immediately tested if some_value == Some(3) { ... } while following along with this and found it worked just fine, so I was wondering what the purpose of "if let" could be. Your explanation clarified it for me instantly.
Thank you. I was thinking something similar and this clears it up well for me.
This is a tool I've been looking for in a typed language for a while now. It seems like I shouldn't have delayed learning rust so long.
Yeah the example wasn't clear this time, the book showed a better example. if-let is used for pattern matching, not for value matching, in that case, an if would be just fine.
Thanks for this comment. Was wondering why he didn't just use an if statement, and what the propose of if let really is. Answered both for me here.
11:30
tested, it works, but is confusing, and I still don't know any case where you would specifically need that syntax, but this also works:
if Some(3) == some_value { /* do something */ }
It was a pretty bad example. `if let` is mainly useful for when you have an enum that holds some inner value in some variant, and you want to access the inner value on _that specific_ variant. For instance:
enum MyEnum {
A(i32),
B(u32)
}
let my_enum = MyEnum::A(0i32);
if let A(inner_value) = my_enum {
println!("my_enum is the A variant with {} as the inner value", inner_value);
}
A similar thing is `let else` which lets you _bind_ the inner value of some variant to a variable, or run some other code if the enum is _not_ that variant, like so:
enum MyEnum {
A(i32),
B(u32)
}
let my_enum = MyEnum::A(0i32);
let MyEnum::A(inner_value) = my_enum else {
panic!("my_enum is the B variant, need the A variant");
}
@@jcm2606 Ah! Thank you very much for the explanation!
Thank you for your hard work. Best Rust channel in my opinion. Keep it up!
It worked. I was a go developer, but I couldn't stand the garbage collection. So now I'm the rustacean!🙂
This was really helpful. Can't read the book rn. Nice to have a quick visual alternative
For the if let syntax, it also reduces the amount of identantion used, e.g:
match some_val {
Some(val) => {
use(val);
},
_ => (),
}
if let Some(val) = some_val {
use(val);
}
Great videos! You explain the concepts really well. Minor thing I recognized: I think you forgot the '&self' as an argument for the method 'fn some_function' at 4:14.
nah, he just created an associative function, but honestly his explanation of impl assumes you know about structs, and wasn't very cohesive. Not to mention he didn't really explain very well how to access pieces of information from enums. I like most of this guy's videos, but this one didn't hit the mark at all.
I've seen syntax similar to 'if let' in other languages. It makes heaps more sense if you consider an example of a bound variable:
if let Some(x) = some_value { ... }
You're conditionally defining "let x" to be the bound value within the following code block if it matches the specified variant.
3:33 - That's not an anonymous struct, since there's no anonymous structs in Rust.
In the Rust Book it's described as "has named fields like a struct does" and in the example it's commented as "c-like structures".
You be starting beef lololol
Shots were fired
Wow. I love this series!
I agree with your thoughts about if let syntax: It is confusing, especially if you look at the "if let" examples mixed with else, else if let, combinations in the book. I bet an Effective Rust book would contain an item "Don't use if let, use match instead.
You can use a more straightforward if:
if Some(3) == some_value {}
Really like your videos, thanks for making them.
Thanks for these videos they are great. The if let syntax looks familiar to c++ if init statements
if let is very useful (succinct) if you use it correctly.
if let Some(item) = vector.get(20) { // or any Option returned by a function
// do something with item
}
That's what if let is for.
The `if let` syntax is confusing to me too, but I think I'm finally starting to get it after I realized that my problem was actually that I didn't understand what `let` means well enough. I thought it just bound the LHS to the RHS, but it's more powerful than that. Conceptually, `let` just fills in the blanks on the left of the `=` to make the left and right sides of the `=` match. So `let x = 3;` is filling in the "blank" (in this case `x`) with a `3` to make the equality hold. More complicated is `let Some(x) = Some(3);` but in this case `x` gets bound to `3` as well. The `if let Some(x) = optional_function()` is true if `let` can do its job of filling in the "blank" `x`. If `optional_function()` doesn't return something of the form `Some(y)`, then `let` fails; otherwise, `x` gets bound to `y` and we can do stuff with `x`.
This article really helped me understand it better: h2co3.github.io/pattern/.
How are you getting the automatic typing in your IDE?
It's a relief to know the if let syntax is confusing for you too, I find it so confusing too, the readability is strange
Bro , you're doing god's work here
Love the flag on the background! God bless America and Rust🦀
Your channel in amazing. With love from Bavaria
Thank you so much for the series, this is super helpful.
As soon as you said there is no null in Rust my mind just exploded.
Lol subbed because of the converting a go developer joke. Definitely hit home for me.
I really like this vedio, it makes sense more than just reading the book!
lol this video just repeats the Rust book chapter about enums. The code is the same, everything is the same
6:50 error on assigning the None it looks like this error only for the newer version of rust
8:40 if I use println!("{ }",value...) , the number"25" would be printed out, but if I type the value(....) function directly like you did in the video , the numbe"25" wont be printed out like your example, so everytime I need to add println!("{ }", value ..) in order to print out the number as well ? and Why the number wont be printed out if I directly type the value(...) function ?
Thank you for your video !
In my example the state is printed out, not the value, and I use the println!("{ }", state) syntax. This syntax is required because the first argument must be a string literal.
How is it different from if (typeof x == "number") {} else {}?
I think it would be awesome if you could provide a useful implementation for the enum method. Great content anyway
as a C++ programmer of 9 years.... these videos are slowly converting me
Wow, it's interesting that you explain a lot of complex concepts very simply, but you find "if let" confusing.
Personally, it's my favorite pattern matching feature, and I think there's a simple way to look at it.
It's just a pattern matching (if) + descructuring (let).
In your example you don't use destructuring, which is probably why it seems confusing:
if let Some(3) = ...
But if you consider an example where you need some heavy duty destructuring, it starts making a lot of sense:
if let Some(Connection(Status("OK"), IpAddr(ip), Port(port))) = wait_connection() {
println!("Connected to {ip}:{port}")
}
obs: The Connection struct is far from optimal, but it gets the point accross.
It should look like this:
if some_value matches Some(3) {
println!("three");
}
@@jabuci Yeah, that'd be easier to read!
In 9:50, its posible to do the same func but instead of taking a i32 takes a ?
I did this but didn't work
fn _plus_one(x: Option) -> Option {
match x {
Some(i: i32) => Some(i + 1),
_ => None,
}
}
11:27 It seems like the syntax is basically a simple if condition with a variable assignment embedded into it, declaring that variable to only be within the scope of the if block and making an assumption on the value of the variable which is guaranteed by the if check. It's doing two things at once and the one depends on the other (hence it can't be in a separate statement). I'm not sure of a better syntax of the top of my head, though when I first saw that just now I'll admit I was a bit baffled by its syntax.
I looked up another example where they actually used the number inside the option enum, `if let Some(i) = some_value`, which made it much better. I haven't written a line of code in the language yet, but it seems like you shouldn't need an if-let expression if you are doing an exact match. Then a simple equality check ought to work (right? Yeah, I should have read some more comments before I made my own).
@@SemiMono That's an error in this video. The if-let syntax should be used for pattern-matching not for value-matching
Do you discuss Ownership with Enums in Rust on your channel? I just came from the book Imma be honest, I don't get it from there. Please help. Thanks!
Using match statement to calculate coin value seems to be overkill. Is there a way to keep coin value inside enum? Like in C/C++ we write enum { nikel = 1, dime = 10 ... }
So from what I understand an enum in rust is used if you need a type that has more than 1 variant of that type?
Yes. An easy example is a token within an AST. An AST can have possibly dozens of types of tokens, but you may want to abstractly refer to any one of those types as _just_ an abstract token. In other languages you may model this with a class hierarchy via inheritance, whereas in Rust you may model this with an enum where each variant is a type of token. One variant is a '>' token, another variant is a '>>' token, and a third can be a generic character token to support identifier characters (ie A-z, 0-9 and _). The '>' and '>>' tokens don't need to store any inner values since you have enough information from the variant alone ('>' is a single >, '>>' is two >'s in a row), but the generic character token needs to store the specific character code of the token, so you'd have that variant store an inner char.
Guys, when I see this ::Output I feel like go back to C, can someone explain? Does his IDE add these small/gray fonts or what?
Yes. Those are type hints and are driven by type inference, since Rust and the IDE are both smart enough to figure out what the type is based on what functions are used and where the value originates from.
Why is it necessary to use String::from in structs and enums?
Because you need to convert the string slice (literal) to an std::String
Why can't we iterated over each of the variants of an enum ? Seems like such an obvious and convenient thing to want to do. Or does it mean I am thinking about and possible using enums in the wrong way ?
You probably are. It doesn't make any sense to iterate over the variants of an enum, as the variants themselves aren't useful. Enums are used to describe types that can take multiple forms, and each variant describes a particular form that the type can be (think an abstract token within a code parser, where each individual type of token is a separate variant). When you construct an instance of the type, you are constructing an instance of _a specific form_ of that type, which you do by selecting _a specific variant._ As such it doesn't make any sense to iterate over the variants of an enum here, either, as you'd basically be taking an instance of a type that is in one form (say Some(T) for an Option) and trying to force it to be another form (say None for that same Option). The instance of that type is in that specific form for a reason, so trying to force it to be another form is problematic and has a very real chance of breaking things (especially if the type is storing any inner data).
Match is so good, it is like switch on steroids
why do you call an attribute a variant?
Something I don't understand about the examples in this chapter is why wouldn't you just say "let five = 5)" then do "let six = plus_one(five)". is there some reason you would want to use Some(5) there?
Instead of using if let I could just say if x == Some(3) {...} so why use if let ?
Good to know that it's not just me that is confused about if let. Match statements are so much more readable. You don't really declare anything new even though you are using the let key word, and just like the match, whatever is in the Some() is scoped. I almost want to go back to Typescript now.
You are declaring something new, the example in the video was just bad. If-let checks the variant of the enum, destructures the enum if it's of the specified variant (ie Some(T) for Option), then binds the inner value of the variant to the variable name within the variant's paranthesis within the scope of the if-let block. The "let" signifies that you're going to be destructuring the enum and binding the inner value to a new variable. Say you had the below function:
fn main() {
let my_string: Option = Some(String::from("Hello, World!"));
}
And you wanted to do print the String behind the Option, _if_ there is a String behind the Option. To do so, you'd do this:
fn main() {
let my_string: Option = Some(String::from("Hello, World!"));
if let Some(the_inner_string) = my_string {
println!("The string is: {}", the_inner_string);
}
}
It's basically a shortcut for the below match statement:
fn main() {
let my_string: Option = Some(String::from("Hello, World!"));
match my_string {
Some(the_inner_string) => println!("The string is: {}", the_inner_string),
None => {}
}
}
The match statement has an unnecessary branch to cover the None variant, so if-let lets you get rid of that and _only_ use the Some variant.
Не зрозуміло чому в останньому прикладі замість порівняння == стоїть знак присвоєння =
Im from Argentina. I don't know if you are saying "NOTA" in Spanish or "Note that". Thanks for your videos man. They are helpful and entertaining
I'm saying "note that"
I'm also confused with Chi Shi. Is it a Chinese girl or simply "cheat sheet"?
@@jabuci it could be a small Chinese cheat sheet, I suppose. Por que no los dos? amiright?
"everytime you subscribe, we convert a Go developer" had me cracking
This chapter made me understand why some Haskellers like Rust.
Best Line --- "Every time you subscribe we convert a GO developer."
after testing I don't see the point of "if let" because regular "if" with "==" does the same
It was a bad example. The key point is that if-let lets you bind the inner value of the enum variant to a variable that's scoped to the if-let block, letting you safely access that inner value within the if-let block, since you've already checked that the variant is correct.
With enums they kinda confuse me
when you have
enum IpAddrKind{
V4,
V6
}
then you create instances of these enum types what does that actually do?
let four: IpAddrKind=IpAddrKind::V4;
like what does ^^ even mean really? what can I do with that info.
Great video btw I just find this topic confusing for some reason.
Internally, Rust uses a special tag to differentiate between the variants of each enum. Basically, imagine if it looked like this:
enum IpAddrKind {
V4, // tag = 0
V6 // tag = 1
}
When you do this:
let four = IpAddrKind::V4;
What you're doing is constructing a value that holds the tag of the variant you've selected, sort of like so:
let four = /* IpAddrKind { tag: 0 } */;
When you do this later on in the code:
match four {
IpAddrKind::V4 => /* something */,
IpAddrKind::V6 => /* another thing */,
}
Rust emits code equivalent to:
if /* four.tag */ == 0 {
/* something */
} else if /* four.tag */ == 1 {
/* another thing */
}
To choose which branch to execute based on the tag. Enums that store data within each variant work the exact same, but also place the data alongside the tag, choosing a specific order based on which is smaller between the tag and the data, since Rust can change the order to potentially reduce the size of the whole enum type. Essentially, this is what it'd look like:
enum IpAddrKind {
V4(u8, u8, u8, u8), // tag = 0, memory layout = { u8, u8, u8, u8, tag }
V6(String) // tag = 1, memory layout = { String, tag }
}
In the above code the quadruplet of u8's and the String occupies the same space in the enum type's memory layout, as Rust knows that you will only use _either_ the quadruplet of u8's _or_ the String _and never both at the same time,_ letting it safely reuse that space to reduce the size of the enum type (look up unions in C, Rust treats the per-variant data as a union). Because Rust has the tag, it can know what variant you're using and is able to safely let you access the per-variant data, like so:
match four {
IpAddrKind::V4(a, b, c, d) => /* something that uses a, b, c and d */,
IpAddrKind::V6(s) => /* another thing that uses s */
}
« Each time you subscribe, we convert a Go developer ». That was offensive. I felt that. 🥺
Is a good developer doesn’t use strings for an IP address but just an u64 that’ll cover the IPv4 32 bit addresses and the IPv6 64 but addresses ;) In the socket layer they are actual 32/64 addresses :)
But I catch your point. Great demo.
Plain if statement seems to work just like if let. So why if let should/must be used instead?
if some_value == Some(3) {
println!("{:?}", some_value);
}
The example in the video was bad. If-let is used for when you don't know what the enum variant contains (ie you don't know that it's Some(3)), but you want to access it and you know it has to be of a specific variant (ie Some(n), where n is the number you want to access). If-let basically binds the inner data of the enum variant to a local variable, letting you access it through that variable, like so:
if let Some(n) = some_value {
println!("{} + 10 = {}", n, n + 10);
}
Very nice! Only weird thing is this `if let` syntax. Don't get why they designed it like that.
The "if let" syntax of Rust is rather confusing, we evaluate for equality using an assignment operator as opposed to an equality operator.
It is weird. Also can it have != operator or is it specifically = only.
Very confusing. Even after googling I don't understand why they chose this syntax. `if let` is pattern matching, so in a sense ìf let` is to `match` what `if` is to `switch`. Except that rust merges match and switch into the same statement, making this even more confusing.
@@wyattbiker Seems to be only =. I tried `if !(let Some( ....` and rustc said "let in this position is experimental. see github issue 53667".
i agree that it's weird, but assignment makes sense because it also binds the pattern identifier
if let Some(val) = func() binds `val` to the value inside Some(_) but does nothing if it is None, unless you have an else clause
same deal with while let
"Welcome to Rust channel. Be sure to subscribe cus everytime you subscribe we convert a Go developer"
I am sorry for my fellow Go developers but I have subscribed.
".. because every time you subscribe, you convert a Go developer.' lmao
Thanks
I Feel personally attacked after that intro cause I’m dropping go as my next language
Don't tell the other Gophers I'm here.
Cause when you subscribe we convert a Go developer
At the rate this is going I'm frankly terrified at the concept of there being 44 videos. If this was C++ (which I'm fluent in) at this rate I'd expect maybe 20 videos.
Watch at 2x speed and it’s basically 20 videos
For C++ and all it's different versions, you need 200 videos :p
wow, you are the spitting image of that Bogdan guy, you should really check him out, he has a channel on youtube called "Let's get Rusty"
I'm still so confused by enums existing as a concept... I mean it's just a "legal" hardcode. Hardcode = bad code, enums != bad code. I don't get it, please someone explain this. I'm 1,5 in programing(C, JS, Python), almost a year of commertial expirience, and I've never used an enums. Literally. Why they are so functional in Rust? It really doesn't make any sence to me
What do you mean by hardcode? The awesome thing with Rust enums is that they're _not_ hard coded, they can accept and store variable values that originate from runtime code, in a way that lets you determine _what_ group of values the enum is currently storing. It's as if you took a union in C, added a tag that told you what variant the union is currently in, then sculpted the language around using that tag to make certain guarantees around the variant that the union is in when it's used in different contexts (pattern matching, if-let destructuring, let-else destructuring, etc). Take any usecase for a C union, add a ton of extra safety features on top that made it safer to use, then imagine the new usecases that would open up if you had that extra safety, and that's why they're so functional in Rust.
Convert a go developer? Oh shit, not another sw eng rivalry :P that's it, in the great tradition of evil emacs, I'm going to wrap all my Go up in Rust calls, and vice-a-versa.
I'm a GO dev, and that hurt my feelings lol
5:10
I'm speedrunning your videos, this shows how much I hate C++
Nice series, but that weird background music/sound/repeating pattern is really putting me off.
hahhaha... I am a go developer... turned by some like... hahahha
Nice VIdeo
Little bit too fast to follow, at least for me. Else very good, THX!!
I thought it was emus instead of enums hahahah
гуд )
Bruh this is literally just the book lmao. I was hoping for something more in depth. It’s a shame there’s so little video content for rust
Yep. It’s almost word-for-word and example-for-example. I will admit, however, getting fed the chapter in 12.5 minutes is a lot faster than reading it myself. But that’s just for seeing the syntax. The diagrams showing the flow of data within memory is (imo) extremely important for understanding HOW rust works, which you don’t get in videos like these.
"The error states that we're missing an arm".
fn main() {
let some_value: Option = Some(3);
match some_value {
Some(3) => println!("This is three"),
None => println!("Nothing in there"),
_ => (),
}
if some_value == Some(3) {
println!("This is three");
}
}
(notice the capitalization)
I think you are going too fast
he's just reciting the book, without really explaining it in his own words.
класное худи))
the syntax of the enums is pretty confusing: < >, ( ), etc
bro just literally took code samples from rust-lang and put it in video :(
Yeah. Why do you think those samples are there? Art-pieces? They are good examples of code in use.
Is there any Russian speaking rust community?
Rust demonstrates how match expressions should be implemented. Switch expressions in JS are just awful...
nice tut, but don't trash go man, they both good langs for different use case
Each sub converts a go dev to a rust dev? Let me just write a bot real quick...
Bro is hating Go
"make sure you subscribe, because every time you subscribe we convert a go developer"🤣 if I unsubscribe, a RUST developer is converted to go?
I enjoyed the content but I am not a convert just yet. You're GOing to have too do better than that ;)