Rust's Option<T> and Result<T, E> containers provide explicit handling for optional values and error states, with Option using None and Some variants while Result uses Ok and Err; key patterns include unwrap() for extracting values with panic on error, unwrap_or() for default values, expect() for custom error messages, ok() and ok_or() for converting between Option and Result, map() and map_err() for transforming values and error types, and the question mark operator for propagating errors up the call stack.
Rust Option and Result: 10 Common Patterns in Practice
Added:understanding the concepts of option and results might be fairly straightforward but using them in practice can get a little tricky let's look at a really simple example never going above a handful of lines of code to walk through many of the most common and useful ways to use these containers option is rust's answer to the infamous billion dollar mistake I'm not actually talking about this that was probably much less expensive I'm talking about the concept of knowable values without proper compile time checks to account for said no ability the term billion dollar mistake came from Tony himself of course option isn't unique to rust some form of option exists in pretty much every language these days and its primary purpose is to make it explicit when something can have no value so an option is an enum generic type T that can have one of two values none or some in Rust each enum value is a struct and in this case none happens to be a unit struct so it's a struct with no fields and some happens to be a tuple struct so it has one field of type T but that field doesn't have a name let's take a look at results so you can see result is very similar to option except instead of one generic type it has two and instead of having a none value it has an error value of Type e so we have two Tuple structs and results okay which has a value of type T and error which has a value of Type e result is rust's way of explicitly defining success in error States and making it easier for developers to proper okay errors up the stack if necessary many established languages use the concept of exceptions to do this but rusts and other newer languages use a special container for return values instead which is what result is it's container for success is called OK and its container for errors is called air I mentioned that the Core Concepts of option and results are fairly easy to understand but there's so many ways to handle and emit them in practice and even translate between them so let's look at some of the most common patterns what we're going to write is a function that takes a vector of strings tries to parse each string into an integer computes the sum of all those integers and then converts the result back to a string and returns it to the color this function is going to be called some stervec so some stir deck it's going to take a vector of strings and return a string first we're going to make an accumulator of type i32 this is going to keep a running sum of the numbers and then we're going to write a for each Loop we could write this in a functional way using the dot map function but we're going to write it as a for each Loop to illustrate some Concepts inside the loop we're going to call to int which is a function that we're going to write that's going to take a string convert it to an integer and return it and then we're going to add that integer to our accumulator at the end of the function after the for Loop all we need to do is convert that integer back to a string and return it to the collar we're at a quick main function to test this out and then we'll go back and implement the two in function in the main function we're going to create a vector with two strings one for three and one for four and then we're going to pass that Vector into some strive get back the total and then print out the total now we just need to implement the two in function the two end function is going to take a bar of reference to a string slice and return an integer all we need to do in this function is s dot parse and then we're going to unwrap and that should do it in the real world we probably wouldn't write a separate function for this but we're going to use it to illustrate a concept s dot parse actually returns a result so if we look at the definition of s-top parse we can see it returns a result result has a function called unwrap that we're using here that's actually pretty simple if the result is of the variant okay unwrap is going to return the value contained in that ok and if the result is of type error the program is going to panic so when you call unwrap you're basically agreeing to let your program crash if there's ever an error result that could be nice for when you're prototyping and building things out really quickly just testing the happy path but generally speaking you probably don't want unwrap in your production code by calling on wrap I'm basically deferring any error handling and I'm saying that if this result is ever of the error variant I'm conceding to let my program crash okay let's test this thing out okay we got seven like we expect let's add some more code in the main function to test out the case where one of the elements of the vector is not actually a number now we've made another Vector that has the string three and then another string ABC which is obviously not a number the first thing we have to ask ourselves is how do we want our program to handle the scenario where some of the numbers in the vector are parsable and others are not do we want some strivec to return an error or maybe none or do we want it to give us a sum of the numbers that are parsable and just assume that the non-partsable elements are zero as written right now the program will just completely crash if any of the elements of the vector are not parsable that's probably not what we want let's run this again and we can see we got seven and then we got a panic we tried to call S stop parse on the string ABC that returned an error and because the result was of the error variant unwrap is going to cause the program to panic and so we can see that here thread main panicked at called result unwrap there's another function of result called expect and expect is similar to unwrap in that if the result is the of the OK variant it's going to return the value contained in that okay and if the result is of the error variant it's still going to panic but you get to specify a custom error message so now instead of calling unwrap or calling expect and we're passing it in a string with our custom error message let's run this okay so yeah we get seven for the first test and then of course we still get a panic but we get a hopefully helpful error message slightly better than unwrap but probably still not what we want now let's assume we want our program to interpret any non-parsible elements as zero that's actually fairly easy to implement using a function of result called unwrap or so instead of expect we're going to call Dot unwrap4 and then we're going to pass in zero unwrap or is very similar to unwrap in that if the result is of an okay variant it's going to return the value contained in that okay but if the result is of an error variant it's going to return the value that we pass in to unwrap or instead of panicking Which is far better in most cases so in this case when we pass in ABC it's going to fail to be parsed parse is going to return an error variant and then unwrap or is going to return the value that we passed in unwrap or which is zero let's try to run this okay that worked so we get seven for the first one like always and then the second one's three because we have three is the first element and then ABC is the second element which is interpreted as zero so the sum is three calling unwrap or and passing in zero works fine if we wanna assume that unparsible numbers are zeros but what if we don't want two in to assume anything and we want the color of two in to determine what Behavior we want in the case where a number is not parsable in that case we'd probably want two in to return an option of an i32 instead of an i32 so if s dot parse returns a result that's of the error variant we want to return none but if s dot parse returns a result that's of the OK variant we'd want to return a sum variant of an option that contains the value that the OK value contains hopefully that makes sense that sounds a little complicated we basically want to convert from a result to an option there are actually functions of both result and option that make converting between the two very easy in this case we get a result and we want to convert it to an option so we could actually just call the OK function and then we change the return value of the function to option of i-32 what OK does is exactly what I just described if the result is of the OK variant it returns some of the value contained in OK if it's of the error variant it returns none and so it discards the actual error value this is pretty handy if we want our function to return an option but it's making some calls to other functions that might return results we can convert those results to options with this extremely simple code we don't have to write any iflet statements or match Clauses we can just dot OK of course now we do need to handle that option in some stervec so let's do that now we're going to write a match Clause here and that's going to have two branches and in the sum case we're just going to return the value contained in sum and in the nun case we're going to return 0. the result of the match statement is going to be added to the accumulator if two it returns sum we're going to extract the value within that sum and add it to the accumulator if two it returns none we're just going to add 0 to the accumulator so it's effectively a no op let's run this make sure it works yep we got seven and three we got the same results as we did last time but we got there a little differently instead of having two and assume that the caller wants unparsible numbers to be interpreted as zero now we're having some stervec determine the behavior when a number is not parsible to do that we have to return an option of an i32 if the number was parsable we return sum of the parsed number if the number was not parsable we return none but because we only need to add to the accumulator if the value returned by 2N is of the sum variant there's actually a simpler way to write this instead of doing a match Clause we can use if let and that looks like this this if statement extracts the value within sum the condition for this if statement says that if the value returned by 2 in is of the variance sum extract the value from that sum and then inside the if block we add that value to the accumulator if the value returned by 2 in is none we don't do anything so that's a little simpler than having that match Clause with both branches for sum and none let's go ahead and run this make sure it works we should get the same result yep and we do but there's actually even a simpler way to write this earlier we saw the unwrap or function of result it turns out there's also an unwrap or function for option so instead of if let sum Val we can just do accumulator plus equals 2 inch unwrap or this is the same thing we did in the two int function earlier but that was a function of result not option the unwrap or function of option works very similar to how the unwrap or function works for results if the option is of a sum variant it Returns the values stored in that sum if the option is of a none variant it Returns the value that you pass in to unwrap or so in this case that's zero what if we no longer want to assume that unparsible numbers are zeros and we just want to fail outright if one or more of the numbers are not parsable in that case we might want to have some stervec return an option as well so let's change the return value of some cervec to option of string and then instead of directly returning the accumulator.2 string we're going to return sum of vacuum.2 string we actually don't need the return keyword if we forego the semicolon at the end of the line now that Sumter VEC returns an option as well when two it returns none we'd want some sir Vector return done as well because it found that one of the numbers was not parsable we could write an if let clause or a match Clause to do this but there's a really nice shorthand to do this in Rust we can use the question mark operator to propagate a nun up the stack if a function call returns none so in the case of two in we have dot unwrap or here we can just replace that with the question mark operator that's all we need to do now if two int returns some for all the elements in the vector we're going to exit the loop and return a sum value with the result string in it if two it returns none for any one of the values this question mark operator is going to cause some stir Vector return a none value because a question mark operator is working on option here and option doesn't have a type for the none variant these options actually don't even have to be of the same type so even though this one's an option of an i32 and this one's an option of a string we can still use the question mark operator in some cervec because it's only going to be relevant when two in returns none which doesn't actually have a type there is also a question mark operator for result that we'll get to in a minute that doesn't have that luxury let's go ahead and run this make sure it works now when we run it this time for the second test here instead of getting a number value we should expect none and we do for the first one we get sum of the string seven and then for the second we get none which is what we expect the downside to some cervec returning an option is that if something goes wrong it's going to return none which doesn't convey any information to the caller about what went wrong the solution to that is to have some cervec return a result instead of an option and a result takes two types the type for the successful case and the type for the error case and for the error case we're actually going to make our own error struct we're going to call it summation error which just is a generic way of saying something went wrong with summing up the numbers for the second type of result we're going to do summation error on the last line of the function instead of returning sum of a q.2 string we're just going to change that to OK of a cube.2string because OK is a successful variant of result now because 2N is returning an option and in the case where the option is none we want to return an error result how do we do that well now obviously the question mark operator doesn't work because the question mark operator returns a none if that option was none so we need to somehow convert an option none variant to a result error variant there's a really easy way to do that and it's with the OK or function we saw okay or earlier again that was a function of result converting to an option because s dot parse returns a result okay or is similar to the OK function up here in that it converts between option and results in this case we need to call OK or instead of just OK because if two it returns a none none doesn't have a type in the case where two in returns a sum variant with a value in it okay or we'll convert that to an okay variant of results with that same value inside it if two it returns a none variant OK or will return an error value of the type that we pass in because result also has a question mark operator similar to option OK or returns a result and then the question mark operator if that result is an error variant we're going to propagate that up the stack so we're going to return that error variant immediately let's go ahead and run this so now instead of having sum and none we have OK of seven that's the first test and then error of type summation error for the second test that's what we wanted now we have some cervac returning a result to it was returning an object option but s-top Parts originally returned a result so it seems like we're doing this in sort of a roundabout way what if we want to propagate any result from s-top parse all the way up to stack to the main function for that we can just change the return type of two in to result i32 and s.parse returns a parse in error so we'll make that the second type for the results and we need to import this and we can get rid of this OK function because we don't need to convert to an option anymore we can just literally return the result that s dot parse returns even though two in and some cervec now both return a result the air type is different so we can't just directly return the result from two in all the way up to stack so let's get rid of this okay or since we're not converting from an option anymore we also can't do the question mark again because that error type is different so let's change the error type of sumpster vect to parse in error see if that works okay so now the question mark operator does work let's go ahead and run this and we get what we expect the first one is okay of seven as always and we get all the details of the error for the second case so it's wrapped in an error variant and it's of type parse int error and then we get a type of error invalid digit we've propagated the error all the way down in s dot parse all the way up to stack to the main function and output it to the console but what if we want some cervec to hide the details of how to int works from the collar of some strivec and we want to return a some serve X specific error instead of exposing the color to the details of 2N in that case we might want to go back to summation error as a return value for some cervec but now we can't use the question mark operator anymore because the error types of the two results are different two in is returning a parse in error and some cervec is returning a summation error now do we need to go and do a match clause or an if let Clause again the answer is no there's actually another function called map error that handles this case easily so all we need to do is dot map error and then summation error and map error takes a closure not just the value so it takes a function that takes the original error as a parameter and Returns the value that you specify so in our case we're just returning a generic summation error that doesn't have any Fields so we can just ignore the value that gets passed in and voila now when two in returns an error variant the map error function gets run and it calls the closure and Returns the value that the closure returned when two in returns okay map error actually doesn't take any effect it just Returns the value that was contained in the OK variant and again we add that to the accumulator let's go ahead and run this and we should see a summation error again for the second test case and yep there it is so that's a quick rundown of some of the common patterns you'll see when dealing with result and option each one has quite a few functions and the meaning of the functions might be a little confusing in general the unwrapped family of functions extracts the value from the container if it's there and if it's not there it does something else that you specify the okay family of functions converts between result and option so if you have an option that you want to convert to a result you dot OK and then whatever flavor of that function you you want if you have a result and you want to convert it to an option you dot OK and it convert it to an option and then finally if you want to change one of the types of the container that's where dot map comes in so if you have a result with one error type and you want to convert to another result of a different error type the map error function would be your go-to and then of course the question mark operator is used when you want to propagate one of the containers up the stack either option or result in the case of option the types don't have to match in the case of results the error types do have to match if you want to propagate an error up the stack I hope this video is helpful for you in understanding options and results and how to handle them thanks thanks for watching and we'll see in the next one
Up Next

Soft Body Physics in Games: From Particles to Simulation
@b2stud
720.3K views•2024-09-22

BitTorrent Protocol Explained: Piece Selection & Peer Choking
@StevenGordonAU
481 views•2013-02-22

HTTP Requests Explained: GET, POST, PUT, DELETE
@codecademy
103.1K views•2021-10-07

Enigma Machine Mechanics: WWII Encryption Explained
@JaredOwen
13.2M views•2021-12-11
Related Study Plans & Knowledge Roadmaps
Structured learning paths in Computer Science



![[s3/5/7 | 2022] Разработка на Rust, Илья Богданов, лекция 1](https://i.ytimg.com/vi/VM7Fpd9XPWQ/maxresdefault.jpg)





![[ПЕРЕЧИСЛЕНИЯ] Rust #16. Создание перечислений и работа с ними. Match. Реализация enum-методов](https://i.ytimg.com/vi/nUP7GGzG0Dw/maxresdefault.jpg)











![Делаем SSG-утилиту на Rust [ IT-X: Mornings ]](https://i.ytimg.com/vi/Aiy6rwQNrds/maxresdefault.jpg)

















