Polyglot Programming: TypeScript, Go, & Rust

Projector Object in Rust: Operation



Polyglot Programming: TypeScript, Go, & Rust

Check out a free preview of the full Polyglot Programming: TypeScript, Go, & Rust course

The "Projector Object in Rust: Operation" Lesson is part of the full, Polyglot Programming: TypeScript, Go, & Rust course featured in this preview video. Here's what you'd learn in this lesson:

ThePrimeagen live codes the operation part of the Projector object in Rust while utilizing traits to define the functionality of each term.


Transcript from the "Projector Object in Rust: Operation" Lesson

>> So let's do the config again. But this time let's try to do it a little bit more rusty, get a little rusty with it as they call it. Actually I don't think anyone calls it that way, I think only I call it that. So let's create of course the enum.

So first off, this is where we're starting, this is where the magic happens, right? Grab a public enum and we're gonna call it an operation. Now before we had Print, Add, Remove, correct, but hey this is rust, okay? Let's do something a little bit more exciting here, okay.

So first off, let's have an option for a string. Now right away that should be pretty awesome, right? Print may or may not have the string, and we can handle those cases differently. We don't have to have an array that has 0 or 1 items in it, we have a much more concrete.

Obviously if you just look at this it's much more understandable exactly what's going on here. Add is gonna be a tuple of String String that also makes a lot of sense, right? You can just look at that and go okay it should only have two values ever whereas an array does not give you that kind of information.

And of course a remove, we can just simply put it as a string like that, you always have to have a single argument. So now it already just shows us right away what our constraints are, whereas the other one you didn't feel it nearly as much. So again singing the praises, praise, praise, praise, praise, praise, awesome.

So how should we do this? Well, there's a lot of things we could do we could do the exact same method we did before where we have all those methods and kind of do them one at a time, but let's do it slightly different here. The first one I wanna do is let's do a trait.

So we're gonna like this, impl from a Vec of string for operation. But we don't want just a from cuz there could be errors, right, we're gonna want a TryFrom. So this allows us to have an error but have all the conveniences of from. So I'm gonna implement its members.

If you have that, fantastic. If you don't, it is what it is. I think we have one question.
>> Why not two values and add string string instead of a tuple?
>> Doing, is he asking this? We could do that as well. That's fine with me. Yeah, I mean, there we go, we'll just do it.

You know what, had, we'll do that for you, because I love you, okay? This is sponsored by me and my love for you. All right, let's move forward. So, what type of error we're gonna have here? Remember anyhow, let's set the anyhow error. Let's go anyhow:: Error. There we go, so we've defined the error type on this, fantastic.

And so now we need to do the try_from. So remember, when we do try_from, what do we see right here? I want you to kind of think about this mentally. What's gonna happen to this vector of string? Well, when we call a method on this, that vector of string can never be used again, correct?

Cuz we're going to consume it. Notice it's not a reference, it is the thing itself. We've been handed the value so we're doing the rust way of thinking right now. We are taking something in and we're gonna create it into something else. There's a good side of that because that means we don't have to copy everything out and create something new we're just simply kind of shifting around where everything points.

So always good to kind of keep that in mind and to think about that. So much like all of our previous ones, let's kind of work through it. So if our value.length is equivalent to 0, well, this should be pretty easy to do right here, right? We're gonna return an Ok, remember Ok is the I have a value in my function that could be an error, right?

So this is that special enum, the results enum. And also let's make sure I do that and make sure we use the anyhow, I forgot about that. Always use the anyhow:: Result, fantastic. Look how beautiful that is. There we go. So we have the anyhow::Result, now we just are returning a result self.

The error property is already an error. Fantastic, so let's do an Ok. And what do we need to return here? Well, let's do an Operation::Print. And what should Print be? Well, Print should be a None, right? There's nothing here. There's nothing we have to worry about. Fantastic, right?

For me, I'm in love, right, I love that, that's fantastic. And then of course we should also add the word 0 cuz that was actually really, really impossible if condition. So now if we have a term, we need to start doing something with this term, right? So let's go like this.

Let's go, if value or how do we wanna do this? Let's grab out the value, I think that probably be the best way to do that. Let's go v equal or I guess arg, we can call this term. Term might be the first one, right, value.get. And for the sake of this get(0 ), we expect this to be here, right?

We've already checked that there's not a length there, we don't need to do anything magical, right, we've already checked the length, it should work. If this doesn't work, something horrible is gone wrong. So expect it to exist, right, it has to exist, fantastic. Now, let's go if term= add.

By the way for anyone that comes from the C++ world, tell me this is not just super fantastic that you can just do string comparisons, right? They're the C world, you can just like, hey, is this string, this string, right, it's fantastic. I just love that. It always feels so good, Rust always feels like a really high level language despite it being much lower than you realize which also is perhaps that's where the biggest foot comes comes from.

Is that it's much dumber and it does exactly what you want it to do. All right, so if we have a term add, now we need to do something with it. We need to take, let's go if term or if value.length, I don't know where I got le there.

I wanna get, if length does not equal 3 we have that exact same error, right? So let's create that exact same error. So I'm gonna go return error anyhow. Bang it's gonna say, hey you don't have that thing in there. And let's create an error from this. Can we import it in?

Now let's see it always gets confused by somethings, right? Anyhow there's that nice little macro right there. And let's go, expected 2 arguments for [INAUDIBLE] let's go, operation add expects 2 arguments, but got percent or this guy, right? And then we can pass them the length of, wrong language, a value.length, weird.

I don't know what just happened there. Length minus 1, right? So I probably have at least one parentheses off. I really wanna reduce these parentheses. I really hate going off the site, and it also is hard at this site. So it looks like this. Let err=, paste all that beautiful stuff in.

There we go, and we can go err, right? Little bit less terrible. It's gonna keep giving you these errors, because what's happening is that the rust analyzer, remember that whole if thing returning values. It's, hey, you've got to the end, but I still haven't seen all my errors yet.

So you're gonna constantly get this update. If you have this in VS code, or if you have it in Vim, you're gonna constantly be getting these updates letting you know you haven't quite successfully written your function. So try not to be too distracted by that stuff. All right, so now let's do the proper value.

So, if we've gotten this, we need to return something out of this. So this is where things are gonna get a little bit interesting. One thing I'm gonna do, is I'm gonna go like this. Let mut value=value. I'm gonna make this thing beautiful, right? And I'm gonna go let mut drain=value.drain.

And I'm gonna drain out two things from this. That means I don't have to copy them out, I'm just gonna literally remove them from the array. So that's one way I could do that or I could pop them. If you pop them you have to do it in like reverse order or I can drain them in proper order.

So that's really the whatever way you wanna do it. So I'll use drain for one of them and then we'll use pop for the other one just so you can see both of them, and that's that. All right, so we have a range from 0 to 2, right?

Sorry, from 1 to 2, correct, right? Drain is an unusual item to use It can kind of be a little bit tricky, but it's also, I don't know, it's kind of fun at the exact same time. So, we already know for a fact that it has to equal size 3, right?

So we already know that position 0 exists, position 1 exists, and position 2 exists, right? So we shouldn't have any worry about these things working. So I'm just go like this, return Ok and I will do a new operation. We'll do an add right here and we need to add in these two values.

So I can literally just go drain-next and then do an expect to exist, right? We already know what should exist, there's nothing, we should not be surprised at this point. Again I'd be very surprised if we were. Let's go like that, take that, do that one more time and there we go.

We have this beautiful little thing. Remember again, it's telling me, this if statement isn't returning anything, something's wrong. Return, I got to figure out something to just put down here, so it stops doing that. I'm just gonna like this for now. So that way we just stopped getting bothered with such nonsense.

There we go, beautiful. All right, so let's do the exact same thing but with term remove. Now remove is a little bit easier because it only expects a single argument. So pop is even easier to use right here too, right, cuz we just simple need to remove only one argument, we don't need to pop two things and then flip the ordering.

So a little bit easier to use, though drain is a fun one to use. Let's just go like this arg= value.pop, which of course, what's the first thing we're popping are popping from the end of the array, which means we're popping out the term we want. So we're gonna pop it and we're gonna expect it, right, to exist right now.

We already know what it should exist, everything about this should exist. We are safe to do these things, we're not worried about anything going wrong here. And let's just go like this arg, fantastic. Now something we could also do is we could do some math. We could do this a bit more clever to really take advantage of some of the options, but I think ultimately this is just a nice, very straightforward way you kind of see exactly what the intent of the code is and you're not gonna run into any problems.

All right, so our last one of course, which is if value dot. Well, actually at this point, we already know we're probably pretty good, right? Except for one thing, we don't know if the length is too long. So if value.length is greater than 1. Well, this is our real only possible problem here, right, it's this thing.

So I'm gonna copy these two, I wanna paste them down here. I'm gonna go to the Remove, turn it into Print. This is a beautiful and go Some, remember because it's an option. So we're gonna return out of that thing. If it's greater than one, well, we only expect one term into Print.

So let's just do that no, operation print expects 0 or 1 arguments, but got that. And let's remove that thing. There we go, perfect. This is identical code to the previous one except for now we're taking advantage of some of Rust's interesting things, traits. So now we can take a vector of strings, call into and transform it into a operation.

I like this a lot, I think this is a great way to go about it, I like using into's, I like this whole from trait thing, it just feels really fun to use. And so there we go.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now