Get your *FREE 4-Day Rust training* : letsgetrusty.com/bootcamp
@viniciusataidedealbuquerqu28375 ай бұрын
2:06 holy cow this graph is so descriptive and the relation between them at the same time is godlevel pedagogy. tysm
@letsgetrusty4 ай бұрын
I got you :)
@tirushone64465 ай бұрын
I like how even after learning rust for over a year lifetimes still scare me deep down, because of stuff like this.
@11WicToR115 ай бұрын
thats the thing i dont like about rust, i mean after years of writing typescript i dont think i would ever find a piece of code in some lib i couldnt just look at and understand, but in rust i feel like i m absolutely not gonna get some of these never ever xD but i can write my snake app in rust and call it an achievement and that gives it a point back :D
@tyrellnelson5 ай бұрын
Lifetimes? Whats that, is that what happens when you call .clone()?
@lobotomy-victim5 ай бұрын
@@11WicToR11yeah typescript doesn’t require a lot of understanding of anything
@11WicToR114 ай бұрын
@@lobotomy-victim thats just a perspective statement, good for you that you left us in the dust
@letsgetrusty4 ай бұрын
Nothing to be scared of! Most of the time you don't even have to worry about lifetimes :)
@undefined245 ай бұрын
**Summary** - Rust drops in revers order - The first implementation, the formatter function's lifetime annotation is telling the compiler that any reference passed into this should live as long as the formatter method live - Due to the reverse order drops, the str variable dropped before the formatter - Redefined the lifetime annotation by using for
@catasterphe5 ай бұрын
too complicated for me but thanks edit: i think i get it now 🔥
@letsgetrusty5 ай бұрын
Awesome to hear :)
@cosmiclattemusic5 ай бұрын
imagine me, a fresh newbie that just started learning Rust jumping into this video. I'm half devastated of how complex this is but excited at the same time, it's gonna be actually fun to learn this well in some future.
@everythingbuttherain63235 ай бұрын
@@cosmiclattemusic pretty sure even if u gonna work with them and use well u still would return back to lifetime docs & explanation videos like i do sometimes)) so don't worry
@cosmiclattemusic4 ай бұрын
@@everythingbuttherain6323 thanks for the really accurate advice ✨
@LtdJorge4 ай бұрын
@@everythingbuttherain6323 also you don’t need to learn this at the beginning. Just start with the things that apply to every language, understanding the standard library, then go on to more complex traits and lifetimes topics. And finally learn every low level detail, like this or atomics, where I find reading the source of hugely popular crates together with the std doc and the book side by side is the best way.
@ARS-fi5dp5 ай бұрын
Thanks to you, i learned memory management, ownership, and borrowing, passing a large portion of the rust learning curve and getting a deeper understanding of low level programming 😀
@letsgetrusty5 ай бұрын
Glad to help! Comments like this keep me going :)
@Starwort5 ай бұрын
5:10 the lifetime is *not* linked to that of the `impl Fn()` (that would be `impl Fn() + 'a`) - instead, it is inferred at its first call site to be 'static, which is longer than the second reference is valid for
@algorythmis48054 ай бұрын
Why is it inferred to be 'static?
@Starwort4 ай бұрын
@@algorythmis4805 that's how it's first used. Arguably it's an inference bug, but honestly it's a contrived example
@flereoussarg16 күн бұрын
I felt something was not quite right about that part, but this clears things up for me, thanks!
@dealloc5 ай бұрын
Now that you are on a roll about generics and traits, it would be awesome to have a video on "magic handler functions", where a handler trait is implemented for closures based on the arguments that conform to a common trait. This then allows the user to define a function whose arguments uses types to "extract" data from a context. Notable examples of this pattern is seen in Axum's extractors and Bevy query and systems. Albeit there are some downsides to the pattern, it can form a nice API without having to do all the plumbing yourself.
@Holobrine4 ай бұрын
Yes please I must understand this wizardry
@poszu4 ай бұрын
AFAIR, Jon explained this in decrusting Axum: kzbin.info/www/bejne/jZ_FkKFrjtCnhZo
@polanas18794 ай бұрын
For anyone looking for a decent explanation, there's a mini book called "Dependency Infection Like Bevy From Scratch" which covers the basics of the pattern
@AndrewBrownK5 ай бұрын
I FRICKING LOVE TYPE LEVEL PROGRAMMING I CAN’T GIVE ENOUGH TYPE LEVEL PROGRAMMING
@hermestrismegistus91425 ай бұрын
You would love Idris. Its types are so powerful that one can prove math theorems at the type level.
@enticey5 ай бұрын
@@hermestrismegistus9142 wait you guys are owning your data?
@everythingbuttherain63235 ай бұрын
caught another typemasturbator here)
@plaintext72884 ай бұрын
Try C, having to memorize all the type shenanigans doubles the fun :)
@nmay2315 ай бұрын
Thank you so much for making a video about this! It's hard to get into and understand high-level concepts like this without a great introduction as you presented it. I have to admit, I'll still need time to wrap my head around all of the implications, but here's a tip for other's who are also struggling. Remember when you have a trait with some methods, you can attach the generic to the trait/trait implementation itself `trait MyTrait { ... }` or you can attach the generic to only the method of the trait `trait MyTrait {pub fn method() { ... } }`. So the first example, where the generic (and its trait bounds) are defined on the struct/enum, means that the generic is unchanging for a particular instance of that struct or enum. In the second example, the generic and trait bounds are unchanging/static for a particular call to a method; this includes the values passed to the method and returned from it. I think higher-ranked trait bounds are the next "russian doll" in this example. So higher ranked traits do not restrict the inputs and output of a method, but instead restricts aspects of the output with respect to itself. An example would be a closure returned from a method, where the closure's arguments are constrained somehow, but not constrained at the time when the method call was made. I write this without a full understanding, so I think the only real takeaway is the russian-doll analogue, if that even helps any, lol.
@Mempler5 ай бұрын
So, tl;dr. In this case, the "for" does exactly the same as
@HaydonRyan5 ай бұрын
Amazingly well done! I found the first half to be a great pace, the second half was a little fast - need to take a breath when ending a complex statement - and a second or 3 more for the code to be on screen. Very advanced topic which is very helpful to have straight forward examples of :)
@polanas18794 ай бұрын
I've never really grasped HRTBs despise reading several explanations, but this video finally made it click. Great work!
@returncode00004 ай бұрын
This is the video I was waiting for 🔥 I always search for explanations on the more complicated stuff in rust but a.) there are not many and b.) most of them doesn't explain it very well or deep enough. I'm also looking for videos who explain functional programming approaches in rust more deeply but there is also not much out there in a digestable format. Anyway, thank you for this video, I'm very thankful you put so much effort into explaining complex stuff!
@clusterdriven4 ай бұрын
This channel is great! Thank you for bringing more of the advanced side of Rust.
@_rushii5 ай бұрын
I never quite wrapped my head around this until now, thanks very much!!
@TheRocreex5 ай бұрын
2:27 I think what you meant to say was the other way round: The input reference must be valid at least as long as the returned reference?
@doesdev4 ай бұрын
The function contract says the returned reference must live at least as long as the input reference; hence the returned reference may only be used while the input reference is valid
@redcoreit5 ай бұрын
Ok, this was 10/10! Excellent complexity/time/depth ratio!
@letsgetrusty4 ай бұрын
Thank you! :)
@iyxan235 ай бұрын
would be really cool if you would dive into those codebases like serde and break down how those types actually work lol
@AreQ2125 ай бұрын
I was definitely missing that part, really appreciate that video! :D
@kolserdav5 ай бұрын
Wow, it's so beautiful and clear code examples 🎉 Good job, Bogdan, thank you 🙏
@el_carbonara5 ай бұрын
thanks it starts to make more sense to me now. glad to see more complex rust as kinda stop learning anything new keeping to intro topics
@bene70425 ай бұрын
I have been programming in Rust for years but have never used this but this is actually really nice and you explained it well!
@ClearerThanMud5 ай бұрын
I've always wanted to understand that better; thanks! BTW, what tool did you use to create this video? Manim? MotionCanvas?
@vondert1735 ай бұрын
Thank you so much! I am planning to start implement complicated closures in my crate. This video 100% saved me time in the future
@EngineerNick5 ай бұрын
Thats very cool thankyou :) Whenever I am writing rust i have this feeling that i should be able to convice the borrow checker of a thing, but I only succeeed about half the times that I should. Hopefully this helps next time I get stuck :)
@ChetanBhasin27 күн бұрын
Hey! What software do you use for your videos? Is that Manim?
@denizsincar293 ай бұрын
Oh i think i got it earlyer. The thing is that a generic type can be restricted by a trait like: fn add(left: T, right: T) -> T { a+b } I didn't test if this compiles. But than i realized that an output type can be different.
@aabhishek49114 ай бұрын
So basically avoid creating code that makes you use this feature, got it.
@theLowestPointInMyLife5 ай бұрын
one of my grievances with rust is the multiple ways you can do things, the example with trait bounds sums it up, you have this relatively complex thing for beginners, and you have 3 different ways of doing it, in the template, with where or with impl it adds much more overhead to reading and understanding code for beginners, one way should be decided on and move on
@vittoriuz5 ай бұрын
Thank you for releasing a video on this topic!
@letsgetrusty4 ай бұрын
My pleasure :)
@emmanueltd76285 ай бұрын
What is the most complicated feature then ?
@danny_hvc5 ай бұрын
My best guess is proc macros
@kadercarter5 ай бұрын
I'd assume the borrow checker
@staywithmeforever5 ай бұрын
@@kadercarter No way borrow checker is this much complicated
@ElektrykFlaaj5 ай бұрын
@@kadercarter borrow checker is simple really. It requires some mental shift when you come from another language, but once you get it, it will be really easy. But macros... oh boy
@taragnor5 ай бұрын
Macros seem the most complicated for me. Mostly because there's no real good tutorial that goes step by step as to what each part of the macro does and then showing what Rust code it expands to and why.
@jonnyso14 ай бұрын
DUDE ! Thank you ! I was reading some source some time ago and just couldn't find out wtf that was !
@MasterHigure5 ай бұрын
2:20 I prefer to think of it as fn first_word(s: &'a str) -> &'b str where 'a: 'b {...} We are specifically _not_ requiring that the input variable and the output have the _same_ lifetime. So clarifying that they are different is much clearer and more transparent than writing it as though they are the same and letting the compiler silently and invisibly subtype it properly for us.
@Starwort5 ай бұрын
Lifetimes are covariant, which means the two are equivalent. IIRC the reference explicitly states that fn(&T) -> &U is equivalent to fn(&'a T) -> &'a U
@Starwort5 ай бұрын
(yep - see Lifetime Elision in either the Book or the Nomicon)
@MasterHigure5 ай бұрын
@@Starwort I'm aware. I just think lifetimes are difficult enough as they are and we don't have to throw in covariance into the mix at the same time, especially when teaching it to newbies.
@jaans37125 ай бұрын
I had one too many whiskeys for this video. I try again tomorrow
@kuqmua7555 ай бұрын
It will be nice if compiler generates error explanation video like yours
@scopulih86585 ай бұрын
Very good explanation, thanks!
@valcubeto5 ай бұрын
Gotta see this video again...
@felixtoulgoat31855 ай бұрын
That's pure insanity... I love it. I should really get started with rust.
@porky11184 ай бұрын
I think I used this feature once. And before I used it, I wanted to use it, because I thought I had seen it and hoped it would be helpful, but then it seemed like it didn't exist and I thought I just misremembered.
@AnassIRIZI5 ай бұрын
great video, simple and to the point
@ARS-fi5dp5 ай бұрын
Thank you 🌷
@NuflynMagister5 ай бұрын
Дякую, Богдане!
@GeekOverdose4 ай бұрын
Idk, I feel like for something to qualify as "second hardest" it would need to be some kind of async ffi proc macro magic, or something
@abduljabbarazam9434 ай бұрын
I didn't know this feature existed, until I found it in Rust Nomicon after watching the video. What's the most complicated feature?
@G117135 ай бұрын
The association of the lifetime of the reference argument to the lifetime of the closure *seemed like* an unfortunate, unnecessary, and counter-intuitive language constraint. However, in the case where the closure collects the provided input such as in an internal stack (aka, FnMut) then such constraints would obviously make sense. With that insight, I suppose the possibility of dynamic mutability within an Fn or FnOnce closure's would require persistence of the provided reference. Nice. Thanks.
@Starwort5 ай бұрын
Except it isn't true. The example at 5:10 is actually just the result of inference. A FnMut with an internal stack would be `impl FnMut(&'a T) + 'a`, tying the function's lifespan to its inputs' lifespans
@damickillah4 ай бұрын
Your paid portal isn't sending me a reset password link. My original password, which I never changed, doesn't work anymore. Can you please advise or assist me with my issue?
@damickillah4 ай бұрын
Let me say, "...which I don't recall changing..."
@letsgetrusty4 ай бұрын
Hey! Which email did you use to purchase to bootcamp!
@damickillah4 ай бұрын
@@letsgetrusty I am good Bogdan. You came through in the clutch and I am commenting here to let everyone know that you a good dude!
@sundae66105 ай бұрын
I'll remember this video for when i need it later haha
@catsolstice5 ай бұрын
Good content 👍
@siya.abc1235 ай бұрын
Rust is the hardest programming language for me because I can't get used to this syntax. I'll stay with Go for now. Maybe I'll learn Rust in future
@samjingwen4 ай бұрын
What's the most complicated feature?
@krakow104 ай бұрын
That's the joke, to make you ask this question out of curiosity Gottem!
@jmstevers4 ай бұрын
is the voice for this video ai generated? or at least ai noise removal?
@johnw.87825 ай бұрын
See new "Let's Get Rusty" video, click new "Let's Get Rusty" video.
@sc5shout5 ай бұрын
so it's like "requires" in c++
@kocsis1david5 ай бұрын
There are a lot of complicated features in Rust. I wouldn't say this is close to being the second one. Many things are more complicated than this.
@thingsiplay5 ай бұрын
I still use Vim/Nvim as my Rust IDE.
@letsgetrusty4 ай бұрын
Don't flex so hard on us mere mortals
@mintx17204 ай бұрын
Wait what if we actually have like `for T: Read`
@nyvyme4 ай бұрын
that's why I prefer C
@nyvyme4 ай бұрын
@@RustIsWinning understandable have a nice day
@Shwed19824 ай бұрын
Ничего не понятно но очень интересно
@omiraclx4 ай бұрын
Now, do subtyping and variance.
@letsgetrusty4 ай бұрын
Someone found the hardest feature ;)
@affanyunas76935 ай бұрын
I still don't understand why I have to use lifetime. Everything was fine before I learned about lifetime.
@LemurFromTheId5 ай бұрын
It's because Rust actually cares about safety and correctness. In most languages lifetime annotations only exist in comments: "This function must not be called after close() has been called for the handle" etc. In Rust, this is encoded in the function signature. Lifetimes are necessarily part of a function's public API: they set boundaries on what callers are able to do with the arguments and the returned value - and what the function itself is able to do internally without breaking the calling code.
@affanyunas76934 ай бұрын
@@LemurFromTheId sometimes the compiler message makes me a little less confident. but it makes me improve myself when writing programs other than rust. shadowing, clone, and error handling make me a little less confident when writing code other than rust language. because my code looks very bad and not confident. i don't know if it really needs to be taken care of, because most drivers are made using c language and they are fine
@NovemberIGSnow4 ай бұрын
@@affanyunas7693 Less than 2 weeks ago, a memory safety bug in driver code brought down millions of computers around the world. I'd rather we switched to using languages that had better memory safety guarantees than C if we're going to execute them in kernel space. Systems programming with lifetimes is annoying. Systems programming without lifetimes is dangerous.
@germanmalinovsky17194 ай бұрын
Then which is the first most complicated feature? Unsafe Rust?
@toby99992 ай бұрын
I'd hate to thiink.... this was already harder than anything I've encountered in C++ in 30 years.
@skejeton4 ай бұрын
can they focus on making the language readable instead
@googleaccount78063 ай бұрын
Higher-ranked trait bounds are too high for my high ass
@fuzzylogicq5 ай бұрын
And y’all still think cpp is harder😂😂…. Saw the func at 0:08 and my brain crashed….well time to go learn zig or stick to just plain old C
@globulonz4 ай бұрын
What are shtrings and conshtraints? 😂
@s1v75 ай бұрын
sometimes it seems to me that rust exists only to demonstrate your intellectual superiority over normies
@pyyrr5 ай бұрын
eh. this problem doesn't exist in c++ which i am thankful for
@arson53045 ай бұрын
crowdstrike
@draco_27274 ай бұрын
Rule number one of Code Club: Never talk about K.I.S.S. -- At least that's what it seems nowadays.
@toby99992 ай бұрын
I still don't understand traits. Sorry. Rust is just way too complex. WTF
@sdramare8645 ай бұрын
unfortunately, in practice, lifetimes and trait bounds make rust code write-only. It's very bad language design here
@simensgreen53745 ай бұрын
Is voice in this video AI generated?
@weeb32775 ай бұрын
no
@megawavez4 ай бұрын
Programming in Rust is a huge brain drain - even simple tasks can require serious mental gymnastics.