Check out a free preview of the full Rust for TypeScript Developers course
The "Options in Rust" Lesson is part of the full, Rust for TypeScript Developers course featured in this preview video. Here's what you'd learn in this lesson:
ThePrimeagen uses Options to eliminate type-checking against undefined variables. The ? operator can be used to unwrap a value by using pattern-matching under the hood.
Transcript from the "Options in Rust" Lesson
[00:00:00]
>> There's a lot of really convenient methods. So I wanna do a small exercise here starting with TypeScript. So you can erase everything. I want you to create a function that takes in a number or undefined and returns a number. You can call the function whatever you want.
[00:00:15]
If the value is undefined, I want you to return 0. But if it's a value or if it's a number, I want you to multiply by 5. The signature cannot use the question mark operator, no question marks for you. You either have to pass in undefined or a number.
[00:00:36]
So I will also write it up myself, erase everything, and I'll go function. I will just call it practice, why not? It's gonna have a value that's a number or undefined. And we're gonna return out a number. Now, of course, if you're pretty familiar with some of the new syntax, the new goodness on TypeScript, you can return, what's it called, value.
[00:01:03]
Let's see, you can do value or 0 multiply by 5. So that makes sense. So if value is not undefined, it will be a value, else, it will be 0. Multiply 0 by 5, it's still 0. We have fulfilled our beautiful interface. Look at that, we have some nice code for it.
[00:01:20]
I assume everyone else got probably arrived to a very similar conclusion, hopefully. All right, so let's do the same thing, but let's do it in Rust. And I'll give you a little bit more time to kinda try this on your own. I'm gonna kinda fly a little bit faster with the TypeScript stuff cuz I'm just gonna assume everybody pretty much knows it.
[00:01:38]
Let's do the exact same thing. A signature that takes in a number or undefined, so that means option bracket usize. So it's gonna look something like I'll kind of help you out here. Let me just do that. So let's go function, we'll call it multiply this time, is gonna take in a number that is an option, say, usize and returns back out a usize.
[00:02:02]
So when I first started out doing Rust, I probably would do something like this. If number is some because it has a value, I'm gonna return num.unwrap multiplied by 5, else, I will return 0. This was probably what I would write at first, right, cuz I just didn't know how to use any of the constructs.
[00:02:25]
Then you get a little bit better, a little bit smarter, and you'll probably do something like if let Some(x) = num. And so now I can go x times 5 and do this, better, right? I'm using pattern matching. I'm solving my problems, but they're still better. Now remember, you can implement methods on enums.
[00:02:45]
So let's go here and go num.unwrap, but look at that, look at all the other ones that are going on there, too. unwrap_or, so I can say, hey, unwrap_or(0) times 5. Give me that inner value or a default value. The default value has to be of the same type.
[00:03:04]
So that's pretty cool. That's very readable to me. I would argue that that is much more readable than something like that. Less symbols, more words, for me, always a good move, I like that. Decide how you will, but, I mean, for me, there's not a big enough difference to make one feel less comfortable than the other, but pretty cool, right?
[00:03:24]
We've actually really reduced it down and it almost is the same amount of code that TypeScript is. All right, so here we go, I'm gonna skip over that part. Yeah, it's much nicer, it's beautiful. So let's change up one thing. So instead of returning 0 if undefined is provided, I want you to return undefined.
[00:03:43]
I know it's gonna change things up a little bit. So that means we're gonna go back to this one, and we have to do something like this. If value equals undefined, return undefined, else, return value times 5, right? And now I have to change our signature. So now we have undefined all over the place, or it's a value.
[00:04:04]
It's a little bit more complicated once we start mixing in this idea of chaining through undefines. We kind of hit this kind of unique place, right? So let's do the same thing, but in Rust. Again, we'd probably do things a little bit different. I probably would've done the whole if let Some business, and then return none, or we can do this.
[00:04:24]
Now, this is where it gets pretty good. We can call map. Map allows you to have access to the inner value if there is an inner value. If there's not, it just remains none. So if you pass to me none, I don't do anything. But if you pass me something, I can say, hey, x times 5, there we go.
[00:04:42]
And then, of course, we have to change this from that to that. So now we've remained inside of an option. We started as an option, we're ending as an option. We're chaining things together. We're doing some pretty cool operations that just aren't really possible in the TypeScript realm.
[00:04:59]
But are you ready for yet another super cool thing we can do? If you have a function that returns an error or an option that is the same type you're working with, you can use the question mark operator. So I'm gonna go like this, let number equals number question mark.
[00:05:17]
What that does is it converts it from an option to your usize. What it does underneath the hood is it does something like this, match number, Some(x), give x out. If it's none, return none. It'll do something like that. That's what the question mark operator does. Effectively, if you're familiar with Go, if err does not equal nil, that's what the question mark does is it does that entire if err does not equal nil thing all in a single symbol, which is just beautiful.
[00:05:48]
So I can literally just go let num = num?. Boom, now we have that, that's fantastic. We unwrapped its value. It's just usize now. And so now I can return Some option num times 5, cuz remember, we're returning an option so we have to recreate it into an option, which means we could just technically put the question mark there, unwraps it does that.
[00:06:08]
Look how small it is. That's pretty nice. That makes a lot of sense. So we look at our two solutions. Let's take a little look. I mean, how does that feel? Feels pretty cool, right? So when you're working with undefines, Rust really try to make it actually be pretty nice.
[00:06:24]
You don't have to do all these wild things. Instead, you have these really nice methods kind of interchanging them or returning them, which just makes life a lot easier. And so in the places that matter, Rust tends to get it right. In other places, I find it difficult.
[00:06:40]
But even though it's great, I already went through all this, it can still be a little bit annoying sometimes. So I'm not gonna just toot the horn and say it's all fantastic. Sometimes enums and all this, they can get a bit verbose. And then now you're finding you're having these annoying pattern matching statements or things around that you could have written a lot easier in TypeScript.
[00:07:00]
But for the most part, it kinda keeps me on rails, and that's what I really like about it is I have to handle situations. I have to be specific with my actions. There is no accidental unknown situation that I might have programmed in, cuz it forces you to do things right.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops