Get your *FREE Rust training* : letsgetrusty.com/training
@darkarchon28413 күн бұрын
Not free though. It's literally just "free stuff won't get you anywhere, you need a project and mentor, I'll be your mentor for some $$$".
@realcundo8 күн бұрын
Nitpick: `panic!()` doesn't terminate the program, it terminates the current thread only. Another thread can then observe the panic.
@linkernick53798 күн бұрын
Nice catch 👍
@jackthereaper93798 күн бұрын
can you tell me atleast briefly how any other thread can observe the panic? I wanna know, it might be useful for a project of mine.
@realcundo8 күн бұрын
@@jackthereaper9379 The simplest is to look at docs for std::thread::Result, there's an example. In short, when you spawn a thread, you get a handle and when you join that handle, it'll return Err if the spawned thread has panicked. It'll return Ok if the thread finished without panicking.
@iceginlychee8 күн бұрын
I would be interested to know as well
@realcundo8 күн бұрын
Weird, I'm pretty sure I replied, maybe it'll appear twice. The simplest is to look at docs for std thread Result, there's an example. After spawning a child thread, you wait for its completion by calling join. Join will return that Result and if it's an Err, the child thread has panicked. Edit: it the result is Ok, it's the value that the function executed in the child thread returned.
@ahmetyazc79698 күн бұрын
I think proper use of panics still has its place in applications, specifically if the error is unrecoverable and expected to never happen. Leaving the app running while the state of the application reached to a point where it should never reach is more problematic, and halting the whole program is the best option.
@rustisbae8 күн бұрын
I would also say its application dependent. For example, you wouldnt want a server just crashing out of nowhere, however a client app could deal with a crash. I just dont like to use panics personally lol 😅
@u-k8 күн бұрын
@@rustisbae But you WOULD want to use it if say, an API key gets unauthorized or a wrongly formatted environment variable is detected.
@rustisbae8 күн бұрын
@@u-k Right, that would be a reasonable to panic. But that's something that happens at startup, not while the server is up and running :p
@letsgetrusty8 күн бұрын
Yes! There are certainly use cases for panic but they are typically infrequent. The problem is developer use panic outside of the specific circumstances you've mentioned.
@jonathan28478 күн бұрын
You should propagate these type of errors back to main and return them from main. Panic has no place.
@RoamingAdhocrat8 күн бұрын
Just want to say how very very nice it is to see the five patterns in the title immediately listed when the video starts. Really helps me orient myself and understand what you're communicating!
@havefuntrading62638 күн бұрын
Sometimes (like 1 out of 10 situations), it's more ergonomic to use panic! rather than introduce bespoke error type. Also, quite a few crates will use panic! internally, so there is not much you can do about it (apart from catch_unwind), even though your crate handles all errors in a clean way.
@letsgetrusty8 күн бұрын
Yes I agree with that when it comes to your own codebase. In terms of libraries, panicking should not be done unless there's a VERY good reason. I'm curious which crates you are referring to.
@omg33ky8 күн бұрын
One crate that panics in a certain case where it is not really good is yup-oauth which is used for authentication with some other Google API crates for example. This has actively impacted me, since there is little I could do about it, but it's a crate where I have done some PRs so when I get time I might implement proper handling. That said. In libs I see very few cases where it actually makes sense to panic instead of returning actual errors and libs should keep that in mind before publishing a 1.0 version imo
@awdsqe1238 күн бұрын
5:26 Think you need to put `&self.settings` even when self is a reference.
@letsgetrusty8 күн бұрын
Yes! Good catch!
@flwi4 күн бұрын
Nice, didn't know that errors convert automatically. 3:45
@Shawnecy8 күн бұрын
If you have only one reader and one writer on different threads, you may want to use Arc instead of Arc. Further for that case of a single reader and writer, if your type is integral or boolean, then you don't even need the Mutex (data that is 64 bits or less can already be read and written atomically via the Arc).
@Imaginary_One6 күн бұрын
If your type is integral or boolean, you really shouldn’t even be using Mutex - you should be using the atomic integral types (but I wouldn’t hold anyone to that!)
@cunningham.s_law8 күн бұрын
if the data is small cloning is faster than arc most of the time
@follantic8 күн бұрын
And clone uses less RAM than Java or JS. RAM is expensive while CPU is often not the bottleneck. And lifetimes can get annoying at times. YMMV
@eli18828 күн бұрын
Performant but more memory usage.
@letsgetrusty8 күн бұрын
Yes good point but then you run into the issue of having multiple sources of truth
@IceQub38 күн бұрын
@letsgetrusty the data is immutable
@paulneal99087 күн бұрын
If the data is small it will be so fast you don't care
@newplayer77438 күн бұрын
New pattern matching syntax that I didn't know about.
@ErikBongers7 күн бұрын
What I like about Rust in this context: a move is typically implicit while a copy often has to be explicit. This helps a lot in avoiding unnecessary copies. In C++ it's the other way round, and you often have no idea if copy or move is being used. What I don't like about Rust is the match syntax: match(variable) { Some(new_variable_name) if => ... You get used to it after a while, but the introduction of this new_variable_name and the extra_condition read unnaturally.
@evols70288 күн бұрын
Be careful when sharing writable data between threads. It can lead to false sharing, which is a degradation of performance when two threads constantly write to data contained in the same cache lane at the same time. In this case, making copies then reconciling them after the fact is better
@penguin_brian8 күн бұрын
Need to ensure error handling provides enough context so that the user can determine source of error. In the example given at 3:40 if the file is not found then ErrorKind::NotFound will be returned, and if this is the only information displayed then the user will have no idea where the error was or what file was not found. On the other hand, panic!() makes it easy to include the filename in the string, and as a bonus you get the line number where the error occurred too.
@jonathan28478 күн бұрын
Error types should ideally be per function and variants per source. So returning an error should give you the exact details where it occurred. A lot of people in favor of panic are just writing bad error propagation.
@spacetowastee7 күн бұрын
Great video! I appreciate the “questions you should ask yourself before you clone()”
@Techonsapevole3 күн бұрын
Great video, it should be in the official doc
@Mempler8 күн бұрын
You can put if statements in matches?!?
@AndrewBrownK8 күн бұрын
It’s the beeessssst
@Caldaron8 күн бұрын
the perfect question for claude/chatgpt
@pmmeurcatpics8 күн бұрын
Yup, they're called guard cases!
@follantic8 күн бұрын
I was genuinely confused by that. 7:55 for reference. Looks awesome.
@BenjaminBrienen7 күн бұрын
Guard clauses
@HagbardCelineOnRust4 күн бұрын
ty for the steady content
@hakanakdag94918 күн бұрын
I am building a secure peer to peer file copy command line tool with rust. Learning it on the way. I found handling errors and result pattern very difficult and concerning. I need to improve these areas.
@evtimpapushev7137Күн бұрын
At around 7:00 I would strongly disagree with the statement about Arc. Rc uses simple increment instruction. Arc requires an atomic operation to be performed by the CPU and those are slow as they need to sync between all CPU cores and even different CPUs in multi-CPU systems.
@basilefff6 күн бұрын
That missing enum variant seems like a very serious issue to me, I would not expect a code to break in such a way!
@s1v78 күн бұрын
explain please how to create custom error types and what are the best practices there
@Nesdac-k1l8 күн бұрын
check out `thiserror` crate for a simple/easy solution.
@TheNoirKamui8 күн бұрын
Also using Box without any good reason. Most of the time it is better to use impl Trait in function properties for static dispatch. Or even better fn() pointers for your own code.
@clot278 күн бұрын
I will keep cloning
@sutsuj64378 күн бұрын
Oh you don't want to clone and instead use a reference? Just re-architect the entire codebase... Nah I'm gonna keep cloning. 'Life is too short for lifetimes
@affanyunas76938 күн бұрын
@@sutsuj6437 i love rust untill i meet lifetimes
@letsgetrusty8 күн бұрын
Just a chill guy who prefers to clone
@theevilcottonball6 күн бұрын
If you clone, you might as well use a language like Swift. You don't care about performance, so there is no reason to use Rust then
@sutsuj64376 күн бұрын
@@theevilcottonball Ok, but if I use Rust I can feel superior over others.
@mihaigalos2796 күн бұрын
hi Bogdan, would you consider compiling a book with these antipatterns? Would love to see some examples of patterns as well.
@iceginlychee8 күн бұрын
Very informative stuff, thank you as always
@qwerwasd17248 күн бұрын
Is panic! okay to use if there's no recovery possible?
@Nesdac-k1l8 күн бұрын
yes, it is usually recommended if unrecoverable.
@jonathan28478 күн бұрын
No, you should propagate errors up to main and return them.
@Nesdac-k1l8 күн бұрын
@@jonathan2847 i hope youre joking
@user-pq5nt1lt7i4 күн бұрын
thanks for the guide ❤🔥🚀
@duck-e2d5 күн бұрын
8:54 this code does not compile fn main() { let list = vec![1, 2, 3]; if let [first, ..] = list{ } } error[E0529]: expected an array or slice, found `Vec`
@JersenManКүн бұрын
Just in case you want to know how to fix it, turn the vec into a slice: fn main() { let list = vec![1, 2, 3]; if let [first, ..] = list[..]{ } }
@SamuelTravnicek7 күн бұрын
In case we are absolutely sure, the function returning Option will succeed, it's perfectly fine to call expect fn. As the name suggests, we expect some value.
@meka49968 күн бұрын
Amazing! Thank you
@christopherpetersen3427 күн бұрын
Feeling good, since I understood what you said and why... O:-) How do you feel about using a suffix like _result or _option on variable names and then the bare (but meaningful!) name inside the Some()/Ok() parts?
@soberhippie8 күн бұрын
The biggest rust sin is not using Rust
@circuitbreaker78608 күн бұрын
Do you have recommendations for how to handle a result in a function that can't return a result? (E.g. closures or implementing trait methods of library crates, that you do not own, which have a overly simply return type like String) Having to discard the entire error stack up to that point always feels so wrong.
@scheimong8 күн бұрын
5:28 I think you need `&self.settings` instead.
@letsgetrusty8 күн бұрын
Yes! Good catch!
@oliverfoxi8 күн бұрын
I thought in Lazy-man error handling you will talk about mindless usage of `?` with anyhow lib
@MechMK12 күн бұрын
What would be the correct way to handle an unrecoverable error? E.g. a program expecting to read data from a file, but the file doesn't exist, can't be accessed, etc... Outside of telling the user why the file can't be read and quitting, I can't think of anything else meaningful to do.
@JersenManКүн бұрын
That is the correct thing to do. Telling the user what went wrong and exiting the program gracefully. If possible you could retry the operation that failed (e.g. network calls to wonky server). Make sure to not retry indefinitely tho. Doing anything is a lot better than just crashing and showing the user a stack trace which they don't understand
@alexkazimir38357 күн бұрын
Cool, thanks 🎉
@MasterHigure8 күн бұрын
Just so it's clear, points 1 and 3 are entirely allowed in Leetcode, Project Euler, Advent of Code, and similar settings. Unwrap and clone everything. Just make it run and get your answer.
@gamekiller01238 күн бұрын
Using unwrap/expect in production code is not an antipattern. Sometimes you know statically that something cannot be None/Err, but getting the type system to help is impractical or impossible. There are also functions with preconditions, and panicking when these aren't upheld to provide a nicer API is fair.
@orterves8 күн бұрын
Unwrap and expect should be avoided except as a last resort and it's better if the function preconditions can be expressed in the input types so that the function can't even be called with invalid inputs.
@Nesdac-k1l8 күн бұрын
yes, but avoid `unwrap` especially since it cannot be given a message. and prefer `assert` where possible.
@Nesdac-k1l8 күн бұрын
@@ortervesoften it cannot be expressed in the parameter types. eg. a parameter for an index in a slice. it could also js be incredibly unnecessary to create a custom type just to ensure some invariant. eg. a non empty vec
@pmmeurcatpics8 күн бұрын
@@Nesdac-k1lfunnily enough `NonEmptyVec` is actually a thing. I was in a situation where I actually needed that, and found out that there's a crate for that™
@pmmeurcatpics8 күн бұрын
"the variable cannot have this value" is better expressed with `unreachable!`
@01joja8 күн бұрын
At 9:07 you switched place on number 2, 3 and 4.
@letsgetrusty8 күн бұрын
Good catch, editing mistake :)
@anon_y_mousse7 күн бұрын
I would consider that broken behavior. If the point of using match with an enum is to handle every case, then extra cases should definitely be an error. I'd honestly like to know why anyone working on the design of that particular feature would think its acceptable to define a new variable especially when you're not using the keyword intended to do so.
@RustIsWinning5 күн бұрын
Tbf that last part is very far-fetched. I want to see a real life case where this ever caused an issue.
@anon_y_mousse5 күн бұрын
@@RustIsWinning Far-fetched or not, I would still consider that broken behavior. Hopefully the next major version number they fix it.
@anlumo18 күн бұрын
I miss the mentioning of the `Arc` anti-pattern, but maybe that's too complex for this kind of video and needs its own instead to explain why it's problematic.
@serbestianmilo14775 күн бұрын
that's not an anti-pattern
@sighupcmd8 күн бұрын
This missing enum variant problem can be huge problem
@aheendwhz18 күн бұрын
Sadly, KZbin shit-translates your chapters when using KZbin in another language than English. I wish they stopped shit-translating things without asking and making KZbin a mess to use in the non-English versions.
@LostRunner02138 күн бұрын
very interesting even for a beginner like me. but youtube enabled the audio translation. what a pain in the a** !
@rezabani99045 күн бұрын
Number 6: Shadowing
@RustIsWinning5 күн бұрын
This one is interesting because there was a kernel bug recently caused by shadowing. I think this is only an issue if you shadow a variable of the same type.
@henning.langhorst8 күн бұрын
The German translation is really awful.
@alerya1006 күн бұрын
Luxury video!!!
@DataPastor8 күн бұрын
How is it possible? I thought, if it compiles, then it is good. /s
@OlavurNonE6 күн бұрын
On the 5. chapter, you switched the title of the 2., 3. and 4. chapter😂 4:32 and 9:08
@v-sig23898 күн бұрын
Please don't use auto-translate for your titles, the translation is unbearable.
@follantic8 күн бұрын
Didn't see an auto translated title, but I definitely still agree.
@letsgetrusty8 күн бұрын
Fixed! YT started doing this automatically -_-
@dagoberttrump92905 күн бұрын
you forgot self referential structs
@tomkimsour8 күн бұрын
la voix française est insupportable et on peut pas la changer sur browser de téléphone. Mais sinon good content
@farfa29374 күн бұрын
You don't handle errors because you're lazy. I don't handle errors because I have nothing to do with an error. We're not the same.
@naive_algorithm8 күн бұрын
I am `unwrap_or` user 😂😂😂
@pierreollivier18 күн бұрын
Man I love how Rust is just becoming C++. You have a problem ? don't worry we have syntax to solve it. Kidding love rust :) (still plz don't become C++)
@RustIsWinning5 күн бұрын
Nice try Zig glazer 😂
@VivekYadav-ds8oz7 күн бұрын
This channel has existed for a couple years and is still making the same basic/trivial content. To grow, you need to keep up with the skill level of your audience.
@brianobot25436 күн бұрын
New people are coming in every day, we need this trivial content since most docs are quite technical so to say
@JurekOK7 күн бұрын
soo . . . rust is mature enough that it has anti-patterns. Uhh. We need a new language that doesn't allow these problems.
@RustIsWinning5 күн бұрын
So basically a language that doesn't allow any kind of pattern...
@spaghettiking6538 күн бұрын
Rust propagandist try not to say "powerful" challenge (impossible)
@RustIsWinning5 күн бұрын
YourMama is powerful (kek)
@mintx17207 күн бұрын
I though lazy man error handling means using `?` everywhere and you get an error up a 100 function call stack and you scratch your head wondering what happened
@chonkusdonkus8 күн бұрын
I really dislike the black background in this video
@CodeVault6 күн бұрын
Please stop with using the term "anti-pattern", it just creates a dogma to not use these concepts even though they have and always will have their uses. Using these "anti-patterns" doesn't make your code more buggy, inefficient or harder to maintain (at least not by themselves. The context REALLY matters) and they certainly aren't "mistakes" as you call them. The first point is the most egregious of them all... Sometimes you want to ignore the return value (the operation simply doesn't matter if it succeeded or not). Sometimes you want an .unwrap() because you already know what the value is. And I don't understand why using panic! is a problem. The second point is fair enough... although, I don't think simply using those traits makes your code any better. Implement them if you need to. That's why Rust gives you so much control. The third point also makes no sense. Sure, you don't .clone() but you instead make another object (an Arc) and also .clone() that as well. How is that any more efficient? Sure, if what you are trying to clone is some huge structure, I understand, but it's just a settings struct. If you need modifying it though, an Arc makes sense. On the fourth point... Most of the time I agree, Rust's pattern-matching is incredibly useful but there are certainly many times a simple if/else chain make things more legible. Context matters. Here I liked the use of matches! btw, I didn't know about it. But still, I am not sure if it is more legible than a simple if statement. Again, context matters, simply replacing a chain of if/else statements with a match statement doesn't make your code automatically better (depends where and how). On the fifth point, again, glob imports are a tool made available to the programmer. It's silly to call such things "mistakes" even though the context clearly matters. Overall, there are things to learn from these videos and I have always found them informative and I thank you for that! You and a handful of others motivated me to start learning and working in Rust. But please, stop making such videos that demonize tools that are useful based on context. This is how we get to creating so-called "best practices" that just make our life more difficult only for the sake of respecting such practices without an objective increase in performance / maintainability / development.
@ol_suh7 күн бұрын
13 And no man hath ascended up to heaven, but he that came down from heaven, even the Son of man which is in heaven. 14 And as Moses lifted up the serpent in the wilderness, even so must the Son of man be lifted up: 15 That whosoever believeth in him should not perish, but have eternal life. 16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. 17 For God sent not his Son into the world to condemn the world; but that the world through him might be saved. 18 He that believeth on him is not condemned: but he that believeth not is condemned already, because he hath not believed in the name of the only begotten Son of God. 19 And this is the condemnation, that light is come into the world, and men loved darkness rather than light, because their deeds were evil. 20 For every one that doeth evil hateth the light, neither cometh to the light, lest his deeds should be reproved. 21 But he that doeth truth cometh to the light, that his deeds may be made manifest, that they are wrought in God. (Jn.3:13-21)