About this video
What You'll Learn
- Start a Rust project by running Rustlings exercises and working with variables, mutability, shadowing, and constants.
- Write and read Rust functions with typed arguments, return types, and implicit return behavior in practice.
- Compare `&str` and `String`, then convert between string types using ownership and deref ideas.
Steve Klabnik, co-author of The Rust Programming Language book, joins to teach Rust from scratch. Working through Rustlings exercises, they cover variables, mutability, shadowing, functions, strings (&str vs String), and structs.
Jump to a chapter
- 0:00 Holding screen
- 0:30 Introductions
- 1:07 Introduction and Guest Welcome
- 1:54 Guest Background and Rust's Popularity
- 3:00 Why Rust?
- 7:01 Rust Community and Tooling (Compiler Help)
- 9:18 Starting with Rustlings Exercises
- 9:20 Variables
- 10:20 Variables: `let` Keyword and Scope
- 16:23 Variables: Initialization and Types
- 21:44 Variables: Mutability (`mut`)
- 24:50 Variables: Shadowing
- 27:56 Constants (`const`) and Explicit Types
- 28:20 Functions
- 29:00 Functions: Definition (`fn`)
- 29:42 Functions: Arguments and Types
- 33:40 Functions: Return Types Syntax (`->`)
- 34:40 Functions: Implicit Returns (Expressions)
- 37:11 Quiz 1 Solution (Functions and Logic)
- 39:45 Strings
- 40:07 Understanding Rust String Types (`&str` vs `String`)
- 44:50 Converting Between String Types and Lifetimes (`'static`)
- 52:24 Deref Coercion for Strings
- 56:00 Structs
- 56:15 Introduction to Structs and `impl` Blocks
- 58:39 Defining and Using Classic Structs
- 1:07:17 Tuple Structs and Unit Structs
- 1:10:08 Methods and Associated Functions
- 1:13:03 Wrap-up and Resources
- 1:15:46 Discussion: Future of Rust
- 1:17:57 Conclusion and Farewell
Full transcript
Generated from the English captions. Timestamps jump the player to that moment.
Read the full transcript
1:07 Introduction and Guest Welcome
1:07 Hello. Welcome to today's episode of Rawkode live. I'm your host, Rawkode. Today, we're gonna be taking a bit of a look at the Rust programming language. We're gonna be doing a few exercises and walking through everything you need to know to start writing Rust yourself. Today, I am joined by Steve Klabik. He is a co author of the Rust programming language, an engineer at Oxford Computers, and a core team member of the Rust project itself. Hey, Steve. How are you? Hey. Doing well. How about yourself? Very well. Thank you. It's almost at the end of my
1:40 day. I believe it's more towards the start of your day. Spread at noon here. So Right right smack in the middle. Awesome. So do you wanna just give us the quick thirty second version about who you are and then we'll dive into today's session. Yeah. Totally. So I've been I've been using Rust for something like seven or eight years now, pretty well before Rust one point o. And I I really love the language, so I ended up being one of the first people to write a tutorial from it and kinda just, like, went from there. And now
1:54 Guest Background and Rust's Popularity
2:09 years later, it's, what I do all the time. So it's been really cool to watch a language go from, like, 30 people in an IRC room to literally being used by the largest technology companies in the world to get all sorts of stuff done. And, yeah, my focus has traditionally been on, like, documentation and teaching people and doing stuff like that. So as you said, I coauthored the the book, which is the Rust programming language, which is kind of the the default book for learning Rust, and I run the beginner Rust training at Rust conf and do
2:37 all that kind of stuff. So yeah. Totally. Nice. Oxide Computer Company is a place that I work using Rust to do embedded stuff. We're building some servers. And So that's what I'm doing, my my day job now. Nice. I like the t shirts. They're pretty sweet. Yeah. Thanks. I think oh, I am so excited by this session is that Rust just seems to be everywhere now. Right? Like, I mean, I kept an eye on it a few years ago, and you could see it growing in popularity. I I think everywhere I look though, there's either people that are writing Rust or people
3:00 Why Rust?
3:11 that just want to write Rust. And I think it's just so available these days. I see a lot of really cool stuff with WebAssembly. I see a lot of people doing embedded systems, something that I think you're working on now. And then even as far as actor based systems and web based systems, Rust just seems to be sweeping. And it seems to be such a popular choice no matter what the domain is. Yeah. I I don't know. Can you explain that? Like Totally. Why is Rust so popular? I think there's a couple of different things.
3:40 So what initially drove me towards Rust was that I've I really like programming languages, and I like learning ones. And I've, like, switched between languages a lot historically. And, actually, I primarily was doing Ruby before I did Rust, to which I joke that I only programming languages starting with RU now. Told that joke in Russia, and I was like, have to learn Russian too because it's also RU. But no. There's a there's a couple different reasons why this happening. So so, originally, Rust is kind of, like, really trying to focus on the sort of c and c
4:12 plus plus use cases, and there hasn't been a lot of motion in that corner of the programming language space. There's been a ton of new languages appearing that are, like, great for higher level things, but there hasn't really been anything that's been, like, a serious competitor in the low level space for a while. And so that's why Mozilla was interested in Rust and why they sort of sponsored the initial development, in the early days is because, Firefox's millions of lines of c plus plus code, and, you know, you don't wanna visit the wrong web page and have some JavaScript, like,
4:43 own you. So web browsers need to be super secure, but you're sort of using these very sharp and very dangerous tools. And so Mozilla folks said, like, what if we could have a a language that's just as powerful as c and c plus plus, but doesn't have as many of the significant drawbacks that they do? And so that was kind of the original Genesis from there. But as it turns out, some of the ways in which we we accomplished that task meant Rod was Rust was, like, a little more broadly applicable. And so it's it's sort of been funny,
5:11 like, over time, exactly as you said, we've seen these other use cases kind of, like, open up as time goes on. And, like, if you had asked me, would I write a web service in Rust eight years ago, I would have said, absolutely not. That would be ridiculous. And now there's tons of people who are doing that even in production, and it's, like, actually a reasonable choice. So that's been kind of a surprise to me. It turns out also that there are other places, like you mentioned, WebAssembly specifically. It turns out WebAssembly has a lot more
5:38 in common with an embedded device than it does with a web page in many ways. And so languages that are really good for this, like, small constrained environment also operate really well in that small constrained environment. So there's been some interesting, like, kinda cross pollination because of those sort of things. And then finally, I think another thing that's sort of driven this kind of renaissance in this area is as we've moved to the cloud and we're built on things like, you know, CPU time, languages that have more performance and use less memory turns into direct,
6:11 you know, bottom line cost savings. You know, back whenever we had our own servers and we didn't didn't like Kara who's super ton about, like, scale, when you had one server and it was running your application, you were just paying for that server and that was it. You know, you could use whatever you wanted as long as it fit on that server. Now when people are spinning up thousands of servers by just, you know, running a small command on AWS, If you can spin up 500 servers instead of a thousand servers, you're gonna save yourself
6:36 a lot of money. And so there's been kind of a a renewed interest in languages that prioritize efficiency, because it directly saves you cash. So that's also, I think, a reason why people are looking at Rust where maybe that wouldn't have made as much sense five or ten years ago. Yeah. Definitely. Well, there's a lot of really good points there. I think that's the best answer I've ever had to an unplanned question. Like, actually, quite in-depth. It's in in some ways, I'm planning for these answers for, like, ten years. It's not entirely unplanned, but you're definitely right.
7:01 Rust Community and Tooling (Compiler Help)
7:08 They're, like, off the off the cuff. I was gonna say the last thing is we tried deliberately to build a really friendly and welcoming community. We're not always perfect at that, but, like, you can get answers from Rust people. And we've developed a culture where, like, no beginner question is off limits. Like, we're super happy to help people, and that's often uncommon in, especially the lower level, spaces online. And so we've also sort of developed a big following because people know and trust that they can get help with their problems without being, like, told that they suck. And that's definitely super
7:38 useful as well. I guess, I got something I noticed in general with not just the Rust community, but the the Rust tooling. There seems to be a lot of effort on documentation and even the compiler error messages and tutorials online. There's just a lot I guess because the community is going so fast, there's a lot of new people and those are those people are getting a lot of help along the way, which helps everyone across this path. Totally. There's there's one guy specifically, Esteban Cooper, who works on error messages, and his kind of approach is that, like
8:06 and we'll see, I guess, how that goes as we actually do this code. But his idea is that, like, the compiler is, like, a pair programmer, and it should be helping you. So you shouldn't just get a message saying your code is wrong. It should try to help you actually figure out what you need to do in response to it. Sometimes it's very good at that. Sometimes it's not very good at that. But, like, a concrete example is Rust has a sync await, kinda like JavaScript does, but we use a different syntax than JavaScript does. So we actually changed
8:28 the Rust compiler knows how to parse the JavaScript understanding of async await, specifically to give you the error message saying, hey. I see you're trying it like this. Turns out we actually do it like that instead, so you should change your code. So that's kind of an idea about how this tooling can, like, help people is, you know, by by not just being like that's an error, but actually being able to understand, hey. I think you're trying to do this because you come from a different language and that's really super cool. Yeah. I mean, async await is one of
8:55 those things. Like, I've written a little bit of Rust to be dangerous, but every time I venture down the async path, I just seem to, like, shoot myself in the foot so many times. And I I don't think that's so much the Rust async syntax with the docs is that I keep trying to do it with Actix, which doesn't have great documentation anyway. So Gotcha. Yeah. It's definitely a moving target in a complicated space for sure. So Yeah. But it's good fun. So let's get my screen share then. So we we have I know we've not done anything in
9:20 Variables
9:22 advance. We've not even had that much of a conversation. As far as I know, of us have looked at the Rustling's examples before, which is what we're gonna be looking at today. Mhmm. If people are curious and want to follow along or do this in their own time, it's just the Rustling's repository on the Rust Lang Gethub organization. Now it seems to have now I know the the bet on the rate is painful to read and I guess I can do my just know and then turn back out. But it's got four quizzes and I figured
9:49 we try and work our way towards quiz one. We'll see how we're doing for time and maybe we'll try and get a few more bits and pieces done after that. Totally. What I would suggest to anyone watching, if there's anything you want us to try and answer questions on or cover or any sections we should take a look at, feel free to drop that in the comments and we'll do our best to tackle that. Now, quiz one. One more. There we go. Requires us to work with variables and functions, which makes sense. Probably, it's two of the
10:16 most common things we wanna cover. So let's grab variables first and see what we're dealing with. So Yeah. To to briefly interject the way that this Rust things kinda works is that you you try to compile the examples and they fail. So this is a not working program. And so we'll, like, run it and it'll tell us, hey. This doesn't work and we have to fix it to make it work. So that's kind of the general structure of this if you haven't heard of Rustlings before. Nice. So we run this Rustlings watch command. My terminal is acting a bit weird. You know,
10:20 Variables: `let` Keyword and Scope
10:47 I'm just gonna do that here. Totally. There we go. Okay. So, yeah, it's trying to compare variables one and this town is a variable cannot find value x in that scope. So let's just take a look at this. Yeah. Now if we look at this code, we can first of all, I mean, we should cover the basic syntax for anyone that's completely new to Rust. Totally. F n, I'm assuming, is a function. Correct. It's how you declare functions. There's actually a fun trivia here. So it used to be in the very old days that Rust had a rule that no keyword
11:21 could be longer than five characters, and that's because they tended to prefer brevity. Over time, we relaxed that, but we sort of kept it where extremely commonly used keynames or keywords are very short and lesser used ones are very long. So it turns out that f n was one that you use all the time. You define lots of functions, and, you know, we we decided it's worth keeping short. So, that's why it's it's, it's so so short. We thought about fun or funk, but in the end, we decided that f n was was good enough. Yeah.
11:53 Yeah. Definitely. Like, I mean, that's that's looks like c style or c's are ever to style code. I guess that most people should find us relatively familiar to them even if we just even if the keyword is slightly different. And I guess this is very similar to go as well, which is also a c derivative. So do you wanna explain the exclamation mark here to people? Yeah. So, basically, this is print l n, which is like print line, again, with a small abbreviation there. But the exclamation point is because this is a macro. So we're definitely not gonna get into writing
12:24 macros in this because, honestly, I'm not even that good at writing macros. But the the trick is is that macros let you write code inside of them that is not normal Rust code, and so depending on the macro, of course. And so the exclamation point or sometimes you say bang means that this is invoking a macro, and so the stuff that's inside might be a little weird. Now, specifically, you might say this doesn't look weird, but it turns out that Rust actually functions can don't have a variable number of arguments. So this, like, if we wanted to just do hello,
13:00 this, this would not work in a regular Rust function because the second version here has one argument and this the the one on line 13 has two arguments. So we use a macro. It's because, we want that extra flexibility, because, as you might imagine, this is going to print the value of x by interpolating the value of x into where the little curly braces are. And so we need to be able to, like, know if you have if you have three sets of curlies, you want three other arguments as well as the string. And so
13:31 the the print l n macro does a whole bunch of really fancy stuff to make all that work and work nicely. Yeah. Basically, the exclamation point is is used when you're when you're doing macro stuff. Very cool. Yeah. Mac metaprogramming or macros is something that I always struggle with. Like, I've written a fair amount of a lecture in my time, and every time I go to write a macro, I still fall over many, many times before I get it right. So Totally. Luckily, Rust has a, like, culture of external packages and letting people use them. So I
13:59 use macros other people have written all the time constantly, but so many people have written so many useful ones that I don't really find it to be necessary to write my own very often. So that's kind of like a a fun interplay of that is that there's definitely a lot of macros in Rust, but you almost never need to write them. You just need to be able to use them. Okay. So let's break down this error message then. It's telling us the x is not in scope. Now it kinda looks like this. This is this
14:26 is subtle. Right? I'm I'm not sure if I understand this, but I'm assuming that this just maybe wants a let here. Correct. So to introduce a new variable, you need to use the let keyword. And that's what this example is trying to teach you. You can't just use the name itself. You specifically say let and then the name of the variable and then an equals and then the value of what goes into that variable. So yeah. Okay. So by adding the let, if I pop over here, it compiles and we passed variables one. Yep. And you can see x has a
14:57 value five because it put the five in where the curly braces were and that's the the bit that it printed out. So yeah. Okay. Can we tackle one more thing on this example then before we move on to variables two? Absolutely. We didn't define a type here when we defined what x is. Is this the compiler doing type inference and and doing that for us? Or is there something else happening here? It's it's specifically the compiler infers the type of what it should be. And so Rust can feel like a dynamically typed language often, but is super super statically typed.
15:31 One interesting thing about this, and I was gonna mention this too with the the function main syntax. So first of all, main is where Rust program start executing. So you're always gonna have a main function somewhere, and that's, like, where things begin. But we require you to put types in for arguments to functions and return types. I'm sure we're about to get into that in a second. So the main function has no arguments and no return. So, therefore, there's no types written there, but you may see types in function declarations. And I'm guessing given that that's
15:58 where we're going next, we're we're about to segue into that. But but yes. Alright. Let's see. Let's just pop open variables too then. I think it says so this paragraph says about this I am done thing. It's like you gotta remove when you feel ready for the next exercise, remove the I am done comment. So I think that that's yeah. Totally. We go. Awesome. Cool. Alright. So I'm done. And then now we have variables two. So our error message is alright. Okay. So x doesn't have a type. Yeah. So this one is, like, a a little
16:23 Variables: Initialization and Types
16:34 bit trickier. So when it comes to numbers specifically, there's a lot of different kinds of numbers in Rust. So we have both signed and unsigned numbers, which basically means, like, is there a negative sign? So unsigned numbers can go from zero to some big number, and signed numbers go from negative some number to positive some number. And so there's there's a lot of them. I think there's, like, something like 16 different types or something like that. Forget. Eight is let's I'll I'll write them out real quick. We got U 8, u 6 Oh, can't type.
17:09 16, u 32, u 64, and 1 20 8. And then so those are the unsigned types. Those can only be positive. And then there's I eight, I 16, I 64, and I one twenty eight. There's also a couple other these are only the integer types. So right there, you can see one, two, three, four, five. So we got 10 types right there. There's also floating point numbers and some other related types. So what's happening here is in the earlier example, we didn't have to write a type because you weren't doing anything with that variable, and
17:46 so Rust just picked the default, which is u 32. But here, it's confused because we have this number 10 and we have this x, and it's like it's really, it's really, like, not it's not understanding what's going on. Now the reason it's not able to understand I'm gonna delete all these type names so this actually works. If you think about this, we never set a value to x in the first place. And so what trying to say, like, they're they're basically, like, Rust does not have the idea of null. So in many languages, if you did something
18:18 like this, you make a new variable and you don't get the value, its value would be null. But here, we never gave it a value at all. And so Rust effectively has no idea what this type is. So it says, hey. I'm gonna compare this thing. I don't know what it is to 10. Is that valid? I have no idea because I don't even know what x is in the first place. So that's kinda like what this is complaining about. Does that make sense? It does. So based on my naive knowledge then, there's two ways that I think we can fix this,
18:45 and I'm gonna see if you can correct me on this. No. I don't know. But if I set this to be an unseen, and let's just say we do an eight, does that have a default value that then that x will become? It does not have a default value. Let's see what the compiler says whenever you you do this because I'm I'm interested in the exact error message, actually. Yeah. So use a possibly uninitialized variable x. And so it's saying, hey. You may have never given this a value. It can figure it out most of the time, but it says possibly
19:15 because it's it's like, you might have do it. I just might be I just might not know. There's some complicated details there. But the point is is that it's like, hey. You haven't actually initialized this to a value, so I'm gonna give you an error. Now there is a way that you can opt in to giving a default value, And so some types do have a default. So I'll I'll let me show you that real fast. Well, actually, let's talk about the other way first because they're gonna converge to to one thing, I guess. Okay. So
19:42 I'm assuming I mean, I can leave that type definition there, but I could also just set it to zero and I could remove that and that would Right. That would be okay. Right? Yes. It should be. Let's see what the compiler says. It works. Yeah. So, so yeah. So now it's, like, looks at it and says, oh, I have a number and a number. Neither of them have types, so they're both U 30 2. So everything is great. And that totally works. And if you were to put back the u eight thing, it would go, oh, then I have
20:09 a u eight and something I don't know what type it is. They must both be U eights, and that's fine. And it just, like, figures it out, basically. The there so you can opt into the default value by doing this. This is maybe slightly more I'm interested to see if this compiles or not, actually. Let's let's run this real fast and just check. It did. It did. So, yeah. So some types have a default value, but you have to explicitly ask for them. So this is saying, there's a thing called a trait in Rust, which I don't think
20:40 we're gonna get to, but they're sort of, like, interfaces if you've used Go or Java. Similar kind of idea. And so you can say, like, please give me the default value of the default interface for this type. And so Rust is able to say, oh, u eight has a default value, which in this case is zero, and we'll actually give you that sort of default. But it's an opt in thing rather than an opt out thing. And you'll see this happen a lot with Rust, which is one of the reasons I think it's a great question that you asked. It's basically, like,
21:07 there's many things where in other languages, something is the default, and in Rust, it's like, oh, that's not there. But if you want it, you can make it happen. And so in this case, you have to you have to expressly say, please give me the default value if you want one. I'm assuming that's just zero. Right? I think I'm 99% sure it's zero, but I don't use it very often. So who knows? We'll find out though. Yeah. Okay. There we go. 0. That would make sense. I I was gonna be sad if it wasn't zero.
21:39 Okay. Alright. Let's remove our I am done. And we'll see what we get next. So variable three with an error. Oh, no immutability. Nice. Okay. Yeah. Oh, let's see if I can articulate the problem here. So we define access three. We are I'm thinking oh, and then trying to reassign it and that is failing. Mhmm. So no. I've written by default is immutable in Rust. Is that correct, Simon? Alright. Yes. So this exercise is what as to introduce the mute keyword. Totally. That works. One fun thing, if you remove the mute and go back to the error that you
21:44 Variables: Mutability (`mut`)
22:30 got previously so when I was talking before about how the compiler tries to help you, you can see that there, it's got this arrow pointing to x and it says, hey. Make this mutable by changing it to mute x. And so Rust is actually able to say, like, this may be what you want. And there's actually a tool called Rust fix that can take these suggestions and apply them to your code automatically if you trust the compiler that much. Every once in a while, it gets it wrong, but most of the time, it's pretty good about understanding what's what's going on.
22:59 Yeah. So that's also a thing. Alright. Let's stick our mute back in then. Let let say yes, and then remove where I am done. Variables four. So this one is actually very similar to number two. So I'm sort of surprised that they're so similar, but it's the same. It it is. Right? It's just a no no value. Right? Yeah. It's like well, it doesn't have one because it's like, yeah, there's no there's no no value. So it's complaining about I don't know what that is. Let's just assume that passes. Yeah. Great. So that's the right one. Okay.
23:45 So let hold on. I'll read my error messages first. So expected string found integer. Yes. Okay. So we define a variable called number. We print it out, and then it's trying to be reassigned and then manipulate it in the next print. Mhmm. Quite a lot going on there then. Yeah. So yes. This is kind of showing you how once you give a variable some sort of value, you can't change its type later. So if this were Ruby or Python or JavaScript, you know, it's totally fine to have something be a string and later change it
24:20 to a number, and that's, like, not a big deal. But in Rust, variables have, like, a type whenever you, you know, make them, and a type can't change even if the value can change to something within that similar type. So yeah. K. So the fix here is just Yeah. It I I find it's interesting. I'm not sure what the fix is they want you to do here, but I can show you an interesting fix, which is to do this. So so this will actually work. And this may be what they're talking about, but I'm not a
24:50 Variables: Shadowing
25:00 % sure. So what this is actually doing is this is introducing another variable with the same name. And so this is not mutating the original number three that's a string. This is creating a new variable with the same name, which means the old one is no longer accessible, and so this actually does work. And this is like a thing that's either really normal to you or really weird to you depending on which programming languages you've used in the past, frankly. I'm gonna go with weird. But Yeah. Yeah. And okay. So that just means we we remove all references to the former variable
25:39 known as number, like, that's Check check it out like this. Maybe this will help make it make sense. So imagine we have a new scope here. So we have curly braces. Right? So now this declares the new variable three, but then it's gonna go out of scope on this line. So now here, the old one still exists. You can kinda think of this like you have a deck of cards. So you have, like, the five of clubs, and you put a new card on top, and it's like the two of hearts. And then later, you pull the two of hearts off, and
26:07 the five of clubs is still, like, underneath there. This would print, like, t h r e e and then five and then t h r e e again because it's kinda like you have this, like, you know, deck of variables. And then I didn't save it, so it's like Awesome. I forgot the new thing. Yeah. Sorry. There we go. Okay. Yeah. So so now you can see how it kinda, like, goes in a scope and then goes out of scope, and the original value is still there. It's just the name is, like, no longer accessible.
26:35 Yeah. And it's kinda, like, not super you know, there's certain situations in which this is very useful, and it kind of makes the rest of the world less complicated. But it can feel weird if you're not used to it for sure. It's kind of a semi controversial choice. Oh, no. Let me remove the I am done. We'll keep Rust things happening. K. And then we'll pop open number six. So here oh, it's trying to define a constant, which is telling us that we have to provide a Type. Type. Yes. And it's actually telling us, hey. You might wanna make this a 32
27:13 digit. Which is the default. So yeah. So so similar to how we define variables with let, we can define constants with const. The difference is is that we don't infer the type of constants. We make you put the type out. And there's a couple different reasons for this, but, basically, a lot of it boils down to it is local variables. You're usually using them in one place pretty soon, and so it's, like, easy to figure out what the type should be. But constants are used globally in a lot of places, and they, like, often become sort of external API. And so you're
27:45 required to write the type down on constants even if you're not on on regular variables. And constants, they're not just constant, but they're also kinda, like, global. So you can see how it's defined outside of the function. We could use this number in any of our functions anywhere as opposed to just in the body of the function itself. Alright. It's always good to understand why these decisions are made. It makes things a lot a lot easier to understand. Totally. I I have often found that when I get mad about something in programming, if I learn about why the decision was
27:56 Constants (`const`) and Explicit Types
28:17 made to make it that way, I'm like, you know, I can see why that choice was made. And so even though it's annoying to me, like, I get it and I get less mad about it. So, yeah. Well, you're doing a lot of embedded systems work now. Right? So you're working directly with Linux syscalls? But not even with Linux syscalls. Like, we are writing an operating system. Like, I'm the one Oh. Building the syscalls. So yes. So I have to deal with the hardware and the decisions the hardware people made and, like, why does this require, you know, doing
28:20 Functions
28:44 this this way and that kind of thing. So the same thing, just one level down like anything. I hope you kept the e in your create SIS call though. Yeah. Totally. Okay. So this never onto the functions elements. It's like, okay. We're gonna understand how Rust functions work. We can see we've got our main function, which we're not familiar with, and it's trying to call a function that hasn't been defined yet. Mhmm. But I'm assuming we can just define our new function. Is is that enough for that to pass? That should be enough. Let's let's give it
29:00 Functions: Definition (`fn`)
29:15 a run. Done. So if we can when we don't provide a return type or even any code within a function, what happens there? Is that just a void type? Or So sorta kinda. Let's see what happens with functions two and three, and it'll be a little easier. I don't wanna, like, get too far ahead of ourselves, and I'm assuming that one of these next examples will sorta get into the details. Yeah. This will be a little a little more helpful. So the the error message let's let's take a look at the actual error message. So
29:42 Functions: Arguments and Types
29:52 there's a couple things going on. As it says, anonymous parameters oh, interesting. That's a funny, not super ideal error message. But, basically, what it's saying here is that numb is a a parameter, but you haven't given it a type. So, it's expecting you to say what the type of numb is. So I mentioned this before, variables get type inference, but the arguments to functions don't. And part of the reason for that is that there's a couple different things, but the primary one is that sort of, like, Rust thinks about the function signature as being, like,
30:26 the contract. And so you declare the contract upfront, and then it checks that the body fits. So I kind of like to think about it as, like, the first unit test. You say, like, I expect there to be this type. And so if it inferred the type, you could make a change in the body and that would change the type of the function, and then you get, like, weird bad error messages. And so Rust's attitude with this is put the types in the function signatures, and then you will get nice errors only in the body of your functions instead of
30:50 if can imagine, like, we go back to the code. If if we change the type of the body here and then this there was, like, a problem, like, up here on line seven, you would get an error message about line seven being wrong when your actual error message would be, like, you know, your app your problem would be down here or whatever. But I said that's the string. We'll see some sort of message that just says Yeah. Let's let's see what happens. It's complaining. Maybe. Yeah. So it expected a string and found an integer because we're passing an integer
31:18 in. We tell it to expect an integer. It's happy. Yep. So this is how you pass arguments, and it's sort of the same as the variable syntax except for there's no let. Right? So you have the name, the colon, and the type just like we had in variables. So ends up being the same thing. Okay. So I'm curious. Like, whenever it's, like, best and we were getting the error message Yeah. It told us that we could also if not using the colon, use at or the pipe. Like, what would what would those be? So it turns out that the syntax is not
31:50 actually, like, a name colon type. The syntax is actually pattern colon type. And so this gets into some more interesting and complicated things. But, like, for example, Rust has two pools. So you could say, like, this won't work because I'm outside of function body, but to give you an example of, like, the syntax. So x equals one two oh, I hit escape, which is bad. So here now x would be a two ball where you have a first element one and a second element two. Right? But because this is a pattern, you can actually do fancier things. So I
32:26 could actually say, let x comma y equals one comma two, and this would assign one to x and two to y. So, so that's like a thing that's there. So there's actually a whole bunch of fancy things that you can do in here. And so, what actually this lets you do is there's there's some more complicated syntax where you can put an at and then some more stuff here or an or and then more stuff here. And so the error message is, like, saying, like, you either need the the type or you need to be doing one of
32:55 those fancier things. So you almost never want to be doing those things, so that's why the error is, like, slightly misleading. But it is technically the case that you could do that if you wanted. Alright. Good to know. So oh, why It's the next example. You removed Yeah. That's silly me. Alright. Okay. Functions functions three. We have an error message that tells us expected one argument. This should be nice and trivial. I'm assuming it just wants us to to fix that. There we go. Okay. On functions four. K. We've got a little bit more code
33:31 here. So we got a main function, setting some integer, and then trying to calculate It's still price. So you can actually see the right by your cursor, there's a little squiggly a little red squiggly right after the arrow. And so I think that it actually it it gives you the error right in line. So Visual Studio Code has really great integration If you install the the Rust Analyzer plug in like you have, you don't even have to run them necessarily. It will figure out, hey. This is I expected a type here. So that's I wanted to point that out
33:40 Functions: Return Types Syntax (`->`)
34:01 too before you, you know, went back over. We could see what the full error is by looking at the terminal or whatever, but you can also get those errors in your thing. Pretty much the same error message. Basically, the same thing. So yeah. So the way that you do return types, you have a little arrow, and then that gives you the type of whatever you're returning. So in this case, we wanna take in a price and then return the discounted price. So we need to take in an I 32, but also return an I 32.
34:25 Okay. That's it. Right? Yep. There we go. Finally, we have functions five. So this is another fun one. So it's saying that expected an end oh, okay. Is this because we don't have a return keyword? Yes. So there's two ways to solve this. There's the, like, idiomatic and the unidiomatic way. It turns out that many languages do the what is unidiomatic in Rust, but you're totally right. Because we don't have a return keyword, this is going to multiply two numbers and then not give you the the value back. So it's, like, kind of like a no
34:40 Functions: Implicit Returns (Expressions)
35:12 op. Like, it doesn't do anything. So if you add return right before the numb asterisk numb, this should work and everything is great. So this works. However, Rust is what's called an expression oriented language, which means that almost everything evaluates to some other value. So you can actually drop the semicolon and the return. And now we have just num times num on its own. The the semicolon basically says, like, hey. I don't care about the return value of this. I wanna just, like, ignore it. So, and that's why it's at the end of almost every line is because, like,
35:47 that's kinda, like, how the structure of the grammar works. So if you do it like this, which is num times none with no return, that will evaluate to nine as well and give you the return value back. And this is very common in some languages like Ruby, for example, and totally foreign if you do see your JavaScript or whatever. This is another example of where Rust has taken an influence from a certain style of programming language that can maybe feel a little bit awkward if you haven't worked in it. And this is probably the number one thing
36:12 that people who are new to Rust kinda complain about. So and part of the reason why is that when you start getting into things like closures, this syntax becomes much more normal and regular and smaller, and so it ends up being a lot easier. But that's kinda jumping ahead, I guess, a little bit. So as the the golden rule there that if you met a semicolon, it's always an expression, which means it's, like, kind of always an expression. You can kinda think of it as, like, expression exists. And if you put a semicolon on it, then you don't get the value. You
36:47 get an empty tuple, which is these double parentheses because, nothing in inside. It's like we had the one and two before. Just an empty tuple. So It's kind of a little weird, kind of a little in the weeds, a little technical. Honestly, the compiler will tell you when you get it wrong and you just fix it one or the other ways. And eventually, you kinda develop an intuition and you stop worrying about it. But yeah. Alright. But I think we have now covered everything for quiz one. Thanks, sir. We could do quiz one, which I guess would just
37:11 Quiz 1 Solution (Functions and Logic)
37:19 confirm that we've learned stuff live. It's basically just writing the syntax that we've learned in the previous examples. Yeah. Okay. So it's telling me I'm not allowed to modify. Okay. I have to write the calculate apple price function. Yep. Alright. Take some price. Another return value. Mhmm. And I should probably redo what it's supposed to do. Oh, it's how many apples I'm buying. So it's if you have more than 40, you it only costs 1. Basically, it costs 2 unless you're doing more than 40 in which it costs 1. So there's, like, a very small
38:07 calculation there. Alright. Well, number of apples. And snake case is the idiomatic Rust approach. Is that right? In so it's snake case for variables and function names, and it's camel case for types. So you'll see, like, capital s string or capital v vec. And that way, can kinda tell at a glance if it's something is a function or variable or a type. And then we return the number of apples times one or the number of apples. So You're close. So because of the way that you've written this, the if statement would return into that number
38:58 of apples, but it's not gonna, like, return it from the function entirely. So you have two have two ways of doing this. You can either make the whole body one if expression. You have two expressions here. Right? You have the if and then you have the second thing. So you're gonna do an if else. That way, the whole body is one if statement, or you can use return to return early and, yeah, that that actually will technically work. I think most people would write it inside the body of the if instead. So, like, online 27.
39:26 Yeah. So this should work, I think. Yay. You did it. And the alternative approach you said there was to to else here so that I only have one expression and then Yeah. And then now both arms of the if evaluate to a value, and then the whole thing gets returned. And so that ends up being the same thing. Yeah. So this is now one expression in the body instead of two expressions. Nice. Alright. Let's see. What does quiz two want from us? So this is the strings. Yeah. This is definitely one of the things that
39:45 Strings
40:03 always trips me up when I'm attempting to write Rust, I should say. Totally. Is that should I mean, what is the idiomatic way? Should I be using string, or should I be using string types? Like, is there a one I should choose by default? Are there any rules? And that maybe we could just start by saying what are the differences between Totally. So for the background, Rust has sort of depending on how you answer this question, Rust either has one or, like, seven string types. Part of that is because in many languages with, like, garbage collection and stuff like that,
40:07 Understanding Rust String Types (`&str` vs `String`)
40:33 strings are a little easier. But it turns out that any sort of variable width structure is really difficult whenever you're, whenever you don't have a GC and some other things. And so, this is kind of like strings are sort of the entry point into going from the absolute beginning. So we've sort of done stuff that looks the same in Rust as in basically any language. Strings are kind of like the usual point where people start learning a little more about the details of things. And, honestly, it's so common that we actually reoriented the table of contents of the book around
41:03 the question of what do you need to get to to understand strings and then how to explain strings as early as possible. So the first three chapters of the book are kind of all the generic sort of syntax that we've talked about so far. And then chapter four is, like, let's get into it with strings. So the way you can think about these, these are the two most core types about strings in Rust. The first one, the ampersand str, if you've done some c or c plus plus languages like that, you may recognize the ampersand means it's like a reference.
41:32 And the capital s string is sort of a what we call an own string type. So sort of the difference is is that the ampersand str is kind of like a you're looking at some other string that exists somewhere, so it's immutable. You can't change anything about it. The capitalist string means that you are the one who's in control of the data of the string, and so that means you can change it, you can modify it, you can grow, and and modify things. And so, that's that's kinda like when you would use each one depends on
42:00 what, you know, what you're trying to do. If you wanna change the string itself and modify it some way, you'd be using capital s string. If you just wanna read the value and you don't care about doing modifications, you would use you'll use ampersand string. And one interesting thing that that kinda, like, comes out of that is it means that you often see ampersand string as arguments to a function, and you often see capital s string as a return type of a function. So if you think about it, usually, you take an argument, you don't change it, you
42:24 just look at it and do whatever. But if you're returning something, that often means that you wanna, like the person who's getting that back is gonna change it or modify it in some way or do something like that. So you can see this exactly on line 12 here. We're returning a capital s string, but, it turns out the string literals are ampersand string, and so it's gonna complain that the types don't make sense. If you if you run the the compiler, it should Oh, I didn't remove my Oh, yeah. Think it didn't get saved on
42:54 variable three dot r s. Oh, yeah. Line four is I'm not done. Although, it's a nice coincidence that I had to open this again, I guess, actually, because we had a question from someone Oh, cool. I missed it. For a quiz one. And I think because this is slightly out of context, I'm gonna try and guess what they ask. But does it work with the parenthesis? And I'm assuming what they're suggesting was this approach, but removing these So those that might be a question. I don't think that's what they asked, but this does not work. It's true.
43:27 Those are curly braces, not parentheses. The parentheses are the around number of apples greater than equal to 40, the the rounded ones on line 26. So yes. And, actually, the compiler will warn you if you put those parentheses in there because they are actually not needed in Rust. And so you can put them if you want, but usually people drop them off. So That's both both versions of if whichever way they meant, those are the two answers to those two questions totally. Oh, you're right. I don't know why I thought those were print, but we're good. That
43:57 was good to know anyway. Yeah. Yeah. I'm so used to this in Go that I now accidentally type or try to do that in other languages and then always end up getting frustrated. So it's good that that works. Yeah. There's actually really interesting history there about programming languages and grammar and stuff, but we're getting too far off topic probably, so I won't get into it. But just the point is new languages have dropped it because they require the curly braces. If you don't require the curly braces, then you need the parentheses more than if you don't. And so that's
44:23 there's there's a whole bunch going on there. It's actually a pretty interesting question if you're into languages. So yeah. Okay. So this why is that one on just primitive types? Why did it go to primitive types? Yeah. Maybe that's because that's the next one instead of this one. But quest two said strings, though. Oh, that's guess okay. Maybe this is not a quiz on primitive types. So that's okay. Maybe that's what it is. Yeah. It's a quiz. We'll we'll just walk through strings one and two and then we can double back. So it looks like we have two options
44:50 Converting Between String Types and Lifetimes (`'static`)
44:53 here then is that and someone has suggested this in the comment. So SDS says, we could just can we change the return type to just be an ampersand string instead of an uppercase string? Yes. So the answer is yes, but there's also a small caveat. So if you try to compile this, it will actually complain. Maybe it's not what to run. Right? Maybe. Yeah. There you go. Right. So it says expected named lifetime parameter. And so this helps as if the return type is borrowed, but there's no value for it to borrow from, you wanna use the tick static lifetime. This
45:29 is very jargon heavy, but the point is, basically, you can return the type. But if, if we go back to the code, I can sort of, like, show you. So since we're, like, referencing a string that lives somewhere else, normally, what would happen is if you have some sort of, like, say that this took this took an a string as an argument too, then I would say, oh, you wanna return something that's borrowing from the argument, and so this would, like, be more normal, but we're not we have no argument here. And so Rust needs to know, hey. You're referring to
46:01 a string, but I don't know where you're referring to or what what is going on. And so there's a special syntax called lifetimes that, and there's a special lifetime called static. So the full name of string literals is actually this, which is ampersand tick static str. And what that means is that tick static means that this lives forever, basically. And so since you have a literal string, it's never going to, like, be deallocated from memory or whatever. Sort of there's a lot of complicatedness we can get into in theory in there, but just the point is that Rust will
46:32 complain slightly and make you put this. So this is a valid solution to this problem. I don't think it's the one that they wanted to give you because it's a lot of syntax for a very little reason, honestly. But it does work in this case. So just to confirm, this applying a static live thing to the string means that for however long our program runs, the string blue will always be stored in memory. Right. And that's because it literally puts the words blue into the binary of your program, and so it's valid forever because it's, like, actually part of the, like, literal
47:03 text of the thing that is on your computer that's running. And if we want you to use the uppercase string, then I'm assuming it wants us to do an actualized access over there. That should also work just fine. It turns out that strings implement a lot of different interfaces. So there's actually, like, six different ways to write the body of this function that will all work. This is the way that I personally prefer to write it. And so this is what I would write if I was writing this code. Okay. Good to know. And I think there was something important you
47:37 were saying you know, when you were explaining it to different types of thing is that if you're returning a string from a function, you probably always wanna use an upper string, uppercase string that allows it to be modified, a hard coded string that you can do and they get away with using an ampersand. Is that roughly what Toy examples like this, you often have hard coded strings, but, like, imagine this is not current favorite color, but this is, like, load color from config file. The value in the config file would not be a literal string. It would be something
48:03 we'd be reading from the file and returning. And so we would want to return the, like, capital s string where it's, you know, you may look at it or inspect it or do whatever later. And so that's usually you'll want the capital s string when you're returning things. Nice. Okay. Strings two. Let's see what we got here. So we're not allowed to change or at least we're not supposed to be changing definition of a word. Mhmm. We are doing an it's color words. Okay. So this is at the wrong type here. Right. And and it's just returning a
48:40 billing based on this expression. Okay. I mean, is that just that? You could you could do this. Yes. I don't think this is what you want they want you to do, but you can definitely do it. So try run it and see if this works. I am, like, 99% sure this will be fine. Yeah. Totally. So that's cool. So we can totally do this. However, I think what they wanna do, there's kind of this joke in in Rust, which is, like, you put an ampersand on it is the default, if the compiler yells at you. So you can convert. So in the
49:10 same way, what I'm I said the ampersand string is like a view into a string that lives somewhere else. So what you can do is there on line nine where you're at, if you make an ampersand word. So it's similar to how they have the ampersand stir. This will kind of this will make an ampersand stir that refers to the capital s string, and so this will also work. And so this is the code that I expect they would want you to write and what is more likely. So this this encapsulates a really common pattern in Rust, which is where you have
49:39 this capitalist string because you've loaded it from somewhere, but you wanna operate on it in a way that's, you know, like, you're just reading the value. And so this is what I was saying earlier about how parameters are often ampersand stir. So all you need to do to convert the capitalist or string into a temporary ampersand stir is you just throw an ampersand on the front of it, and then that will coerce it appropriately. Okay. And the reason we wanted that approach instead of best approach is, I guess, because of the move semantics as well? Yes. Totally.
50:09 So if if I were to print word down here, this will yeah. This would fail to compile because, as it says, you've you've moved it into the function. So when you when you pass a capital s string, you're saying, like, hey. Here's a color word. This is your string now. Feel free to do what you want with it. And, at the end of the function body, it will deallocate that string. And so it will just, like, totally throw away all its contents. Whereas if you use the ampersand version, you're just passing in a temporary view into that string
50:43 instead. And so, you know, everything will be peachy keen afterwards. Yes. I guess I mean, one of the nasty habits I seem to have got when I write some Rust now is to throw in dot clones. Yeah. This would also technically work. What this would just do is copy the memory, and so this will basically just be very, I mean, it's five letters. Right? So it's going to be extremely slower and use a tiny bit more memory, like an imperceptible amount. So it's definitely not a big deal. And if you get your code to work with the clones, totally super
51:16 fine, especially when you're starting out. The important part is to get your program working. It does not matter if it's the fastest possible thing. Like, one kinda interesting pattern is that a lot of people who are new to Rust make things harder on themselves than they have to be. Because once you're given the power of, like, making it so fast and small and tiny, you will, like, want to make it the case that it is that fast and small and tiny. And so people will go to great lengths to avoid typing out a clone when, like, they could just have their program
51:42 working. And, like, this will still be faster than your Ruby or Python and still use less memory even though you're making an extra copy. So, like, don't sweat it when you're starting. Just, like, throw a clone around. It's, like, it's totally fine. Not a big deal. Alright. Well, we'll leave that like that for now. Well, I don't know if we'll make it to move semantics, but we'll definitely have a look anyway. So we got two comments on this example. So SD is back and saying, when we use string from, is this resource from the heap?
52:09 Yeah. So what happens is is the string will will allocate some memory on the heap, and then it will copy the green into the heap afterwards. Yeah. It doesn't it doesn't necessarily take it from the heap. It puts it on the heap, but I think that that's what you were trying to ask. Yes. And Sev is asking, and this could because I actually had to stop too. Is there some magic between the ampersand on the string that casts that to Yeah. Yeah. This is a great question because I I was I was trying to see if no one would
52:24 Deref Coercion for Strings
52:35 notice. So you've got some sharp viewers. So technically, yeah, what what you may notice, if you think about it in terms of, like, forget that. Yeah. It does go down. So, if you think about this, like, you know, okay. I have a string, and then I'm gonna close the little terminal I have because I can't see this well. And then I put an ampersand on the front. That makes it a capital ampersand string. So how do we get a stir out of this? And the answer is is that in Rust, there's an interface called dRef.
53:05 And what that means is dRef. And so there's a special way that you can implement deref to do coercions. Rust, generally speaking, does very few coercions implicitly on its own. This is one of the only cases in which it will enable a coercion. And so, basically, what ends up happening here is that the the implementation there's gonna be a lot of syntax here. So I'm just gonna, like, show you, and then we'll, we'll, like, not worry about it because, like, there's gonna be a bunch. But in the standard library somewhere, there's some code that looks like this.
53:46 I changed. I copied and pasted some some lines. So I think it looks like this. I totally forget. Anyway, this is a whole bunch giant pile of garbage. The point is is that it says, like, if you have a string, you implement d rep for it, and the type that comes out is this stir. The reason there's no ampersand there is complicated and far too advanced right now. It doesn't matter. But the point is is that, like, there's this there's this implementation. You can go look it up if you really wanna know how it works.
54:16 But whenever you have string d refs to the target of ampersand stir, that means an ampersand string can turn into an ampersand stir. And so, this is just one of those magic coercions, and that that, it's like it's like one of those things where and this is why throwing ampersand on it is, like, often the solution to things in Rust because, like, many things will have this this pattern of, like, there's the type that is owned and mutable. There's the type that's viewable and, like, not changeable, and you implement d rep between them so you get this nice coercion.
54:48 So that's the that's the high level version of that answer. And you could you could fill up a whole podcast with just the details on on specifically how all that works and, like, a bunch of things. But, yeah, that's basically basically what it is is Rust will coerce it, and there's an interface you can use on your own types if you wanna implement that coercion. That's pretty cool. It's it's nice that it's just using, you know, the different tree implementations, and there's not just some hardcore compiler magic that knows kinda what to do there. Like
55:12 Yeah. There's a lot of things like this in Rust where the thing that is like would normally be compiler magic is hooked into via some sort of trait. And so you could implement the trait on your type and have access to the exact same same magic. It's very common in a lot of places. Alright. Let's move on then from there. So was gonna move us on to primitive types. Let's pop that open. So now we're looking at, oh, billions. Okay. Yeah. This is very similar to the stuff we've done before. Sometimes Rustling goes very slow
55:43 because it's designed for being a single person with no help on their own. So it does a very good job of taking very small steps. But, you know so we've we've kind of already covered this, which would be great practice if, you know, I wasn't here. But I I think we've talked about this a bunch, so this should be pretty easy for you. Well, why don't we just pick something a little bit more interesting? Yeah. Sure. We we've got about, say, twenty minutes left based Cool. Roughly. So let's see. What have we got? Let's close
56:00 Structs
56:09 it down. Oh, exercises. Is there anything that you think would be fun to go through? I think maybe one good example next, so we have twenty minutes, is, like, in the intermediate part is sort of, like, structs. Because I wanna show you how you can define your own types in Rust because that's also a useful sort of thing. This is Rust analyzers on my side. It's got a lot of yeah. My my screen looks very different than yours. It's kinda funny, actually. Almost all of the little, like, things where it says zero implementations on yours
56:15 Introduction to Structs and `impl` Blocks
56:41 Say, like, missing command on mine. So that's kind of interesting. I have to file a bug about the live code share, etcetera. Yeah. Where's my Rust Analyzer Revolts, Griggles? Yeah. Yeah. You've got it's good. So well, part of it's because yeah. Anyway okay. So, let's let's just get into it rather than talking about bugs in the in the IDE integration. So, on line six here, have a struct. And so Rust doesn't have classes. It doesn't really do object oriented programming exactly, but it can feel like it's sort of you've seen methods already and stuff like that. So the difference is
57:12 that Rust has structs. So, like okay. Classes in an object oriented programming have sort of two things. Right? You have the data and the behavior, and they go together in a class. And so Rust kinda says those are two separate things, so we should separate them. So instead of instead of classes, we have structs, which are purely data, and then we have functions and methods that are the behavior that operates on the data. So there's a little more separation in Rust than there is in other languages. So here, we have this struct, color classic struct,
57:42 and there's no data inside of the body of it. So it's not, like, super useful because there's there's nothing there. So if we look at down at the examples and, like, what these tests are kinda doing, we can sort of see what they want us to do. So let's see. So it's gonna complain about green doesn't exist and then the name being this classic struct thing. So I look up here. Yeah. Color classic struct. Interesting. So I don't know why it's referring to these as classic c structs. Maybe we'll figure it out as we type stuff here. But
58:27 down here on line 22, where it says let green equals. So the thing it's saying is, like, we have all this color classic struct, right, from above. And so this would be how we would, like, instantiate it as we said the name and then the curly braces. But it's gonna complain because we don't have a name and we don't have a hex. So you can see on line twenty six and twenty seven, use green dot name and green dot hex to get sort of these, like, values. So what we'd want to do here is we would wanna say name
58:39 Defining and Using Classic Structs
59:03 is green and hex is bound zero zero f f zero zero. And so this, like, this would work from declaring the body of it, but it's gonna give us an error about defining the struct up above. So let's, let's briefly jump up there, and we'll also check those out. So color classic struct up here. We would have, name is a static str, and hex is also a static str. So I think that this text will now test will now work. Let's double check that's true before we talk about what the syntax looks like. So this is complaining about 38. So this
59:54 is the other test. So think we're good. Cool. So yeah. So with the struct, if we look up here at line, eight and nine, very just much like we had the name colon type with variables and with function arguments is the exact same thing in struct. So here, this color classic struct ends up being, as two sort of data types inside of it. So one string with the name and one string with the, hex decimal value of what the color is. I'm guessing this is kinda like CSS colors or RGB values in general where it's got some sort of name
1:00:27 associated than the actual type. And so that's how you declare it. It's like a struct, name of the struct, curlies, and then the same name and value pairs. One thing you'll notice is that there's a trailing comma here on line nine. So Rust has support for trailing commas, and, so that's really, really nice. Every time I go back to JavaScript or JSON and I can't put a trailing comma, I get a little sad. But, you know, this is like a stylistic preference. You don't have to put one there. If you leave it off, that that will
1:00:57 work. But, it's usually people put them in because that's the preferred style of things. So in the same way that's how you declare a struct, we when we instantiate one, you can see on line 24 to 27, it's almost the exact same thing as when we, like, assign a variable to value except where, you know, we're let green equals and then struct. And then inside of it, we have the name as green and the hex is that value. And so the the syntax mirrors the kind of declaration syntax in the same way. Okay. Did you use a
1:01:27 a static livestream string because of these assertions, or would that just be, like, common practice to not use this I use it because of the assertions. Usually, in the same way that, like, if you return a value, you will often return a capital s string. Most of the time in a in a real world, Chuck, like, imagine again, like, I always go to the config file example because I think that's very intuitive. So if we were gonna be loading this color from a file, we wouldn't have a string literal, and so I would use a capital
1:01:54 s string. And so I I purely just did that because there are string literals in this text. But normally, I would I would sort of default personally to to making this a string and making this a string. And that will, like, work. It just means that this is gonna get a little weirder. We'd wanna do a string from down here and then same thing here. And then finally, I think this might this might compare or might not. We may have to toss the ampersand on it to get it to work. But, like, this would be what the string
1:02:28 from version would look like. This looks a little grosser in the tests, but it's more likely to reflect what, like, actual real world code would look like. Is there a macro for creating a string that simplifies the syntax? The thing is is that, like, someone did release a crate, like, a crates or packages in Rust. So somebody did release something that would let you type s bang. But, like, is it really worth getting a whole external package just to eliminate, like, five or six characters here? Like, generally not. It's just like it's like it's it's one
1:03:02 of those things that it's like, it is slightly unfortunate that's a little long, but it's also not long enough to be so much of a pain that you, like, resort to something like a macro to fix it. There may be someday, maybe string literals will just coerce into capital s string automatically. There's definitely some people that want that. There's some people also that because of that heap allocation, there would be upset that we'd be doing heap allocation implicitly. And so there's kind of a a battle over whether it's a good idea or not. Okay. Let's remove that. So there was a a
1:03:36 question. I was gonna keep the layer, but because you're kinda talking about battles between what people wanna see, maybe it kinda nicely segues in. But we had a question that said, Rust is very readable and enjoyable. Or what does the team take into mind when it's trying to add new features and it's referencing things like c plus plus 20? Yeah. So I I think the interesting thing about the wording of this specifically is, like, to make it complicated and ugly, or are they trying to say to not make it complicated? Yeah. Okay. Cool. There we go. Yeah. Awesome. So
1:04:09 one kinda, like, interesting thing about Rust and its syntax is a lot of people hate it, and a lot of people don't understand why other people hate it. And the reason is is that Rust really draws inspiration from a lot of other languages. So almost nothing in Rust is actually new. Many of the things the the name specifically is, like, evoking the idea of a well worn tool, like something that's been around for a long time. And so, like, the a lot of the syntaxes are drawn from, like, several disparate sources. So, like, you have some stuff that's a
1:04:45 little c inspired, some stuff that's a little, like, ML or OCaml inspired, some stuff that's a little Ruby inspired, some stuff that's a little Python inspired. And that means if you, like, if you don't have the particular background, it can feel really, really strange. But if you do, it feels really, really normal. And that leads to a lot of areas in which, like, people will kinda be like, you know, why is it written like this? Because, like, no language is these are like this. And they're like, well, if you've programmed an OCaml before, actually, this is the exact same syntax.
1:05:17 And so, you know, or whatever. And so there's there's definitely sort of kinda, like, fruitful, arguments to be had. I think the thing is is that, specifically, referring c plus plus one of the things that's a challenge for c plus plus is that it originally was very much, like, an object oriented language that was, like, very much designed in the late nineties when it was first released. And then over the last, like, fifteen years, they've tried to morph it into sort of, like, a more functional ish language. And so when you it's kinda like trying to change the engine
1:05:51 on a car while you're driving down the highway. Like, you can do it, but it's, like, very complicated, and there's a lot of constraints on the problem and, like, you know, you've got all these things going on. And so I would say the number one thing that we have in Rust to make it feel more simple is purely that we started so much later, and we haven't gone through that process of, like, let's mutate it into something else entirely means that there's a lot less weird corner cases because we we haven't, like, done that make of a drastic change. And so I
1:06:20 think the number one thing that we can do to make sure that Rust does not mutate into something like that is basically to say they're like, we're never gonna like, go ahead and make a new language that replaces Rust someday rather than trying to turn Rust into a totally different language incrementally over time. So that's kind of, I think that's sort of, like, the key to it. It's, like, making sure that the bits stay orthogonal and that we're not trying to, like, change the core nature of what Rust is over time. There are good reasons why the c plus
1:06:52 folks are doing what they're doing, and and kinda like that's one of the reasons why it's still maintained its position of dominance for so long. So I don't wanna say that that approach is wrong either, but I think that we're kind of more, like, in the interest of, like, we're gonna keep the core Rust the same way it is. And, like, maybe another better language will come along someday, and that's just kind of the natural way of the world. So it'll it's fine if we let that happen. Nice. Cool. Okay. So shall we I think the other
1:07:17 Tuple Structs and Unit Structs
1:07:20 example in this file is to take a look at a tuple based struct. Mhmm. Do you want to do that or will we look at yeah. You can do that real fast because it's not too long. So in the same way that I talked briefly about tuples before with, like, let x equals one two. So this is, an anonymous tuple. Like, there's no name. You can also declare, like, a struct that looks like a tuple. So what you put here is string string. And so you can kinda see how it looks sort of similar, but it's just the type, no
1:07:49 name, and then the type. And so that means that down here, it would say, let green equals color tuple struct, and then that would be string from green and string from pound o o f f o o. And so this kinda looks more similar to a tuple, but the name it's got a name to it instead of it being anonymous. And so the way that you access we don't have names. You access them by numbers. So dot zero and dot one would give you green and zero f zero zero because we haven't done the name.
1:08:30 And so, like, under the hood, this operates the exact same way. Just like sometimes one or the other feels more natural in a given situation. And so, you know, if you have something that's very simple and small, like, if you have a point, you know, maybe you don't wanna go the whole x y z, maybe just like zero one two is, like, good enough or whatever. So tuples tend to be good in very simple circumstances, and giving things names tend to be useful when you have something that's a little more complicated. Nice. Okay. And are you do you know what the final
1:09:00 one is about? The unit The final one's unit struct is you could have a a a struct that has no data at all. And so this is called a unit struct. And so to do that, you just say let unit struct equals unit struct, and it just exists. There there are some reasons why this is useful if you want, but we probably should since we have limited time, I don't wanna get super into it. But just like the point is is that, you know, you can have any number of things you want, including zero things.
1:09:30 So yeah. Alright. I'll I'll pretend I'll know what that one's for then. Okay. Totally. It's fine. Okay. So do wanna do struct two, or do you wanna jump into something else? Let's let's briefly let's not do struct two because this is going to some other things. Let's check out struct three real fast because I wanna see if right. So this is gonna cover methods, which is, I think, gonna be interesting. We can just go over it really briefly. You don't have to go into all the details. But point is, like I said, we have this
1:09:58 separation between the data and the behavior. So here we have our struck package, which has a country, it's a string, and recipient country, it's a string, and then a weight is I 32. So this is just purely the data. We use the import keyword to declare an implementation of package. So this is saying, like, this is gonna be all the methods that are involved. And so, here we have three methods. One is new, one is is international, and one is get fees. You can kinda see the, some of the versions of this index here. So this
1:10:08 Methods and Associated Functions
1:10:28 is what would be called a static method in other languages. We just call it a a associated function in Rust. Details don't really matter. The point is is that this would take three arguments, the country, the recipient country, the weight in grams, and we'll return a package. And so you would, like, you know, return the value by creating this struct. So, this because it gets declared down here. So package colon colon new is how you'd invoke it, and you'd be able to pass in those three things, and you would get a package back. If you wanted a method that lets you
1:11:00 do, like, method syntax like foo dot bar, here, you would take a the first argument is this self argument. So it's very similar to self and JavaScript or Ruby or Python. We're explicit about it like Python rather than implicit about it like Ruby. So the the first argument being self means that this would be a method. So if we had, say, a package of some kinds, then we could say p dot is international, and that gives you that method to call to next. And so this gives you Rust sort of like an o o kind of,
1:11:32 like, feel because you have these methods, but it's a little cleaner and that your data and your behavior are cleanly separated as opposed to being declared in all of one thing. And in this example, you might say, like, that's not super useful because you just declare both of them anyway. That's totally true. Part of it is because sometimes you only have data until you just have structs. And so rather than having two separate concepts, a struct and a class, you just have one. Everything is a struct. Sometimes you have methods. Sometimes you don't have methods, and that feels a
1:11:57 little cleaner. Also, it's because you can declare methods on other people's structs if you want. And there's some interesting rules about those details there, but by splitting them up into two separate things, you get that control over, like, sometimes you just have data, sometimes you have both, sometimes you put your own methods on someone else's data. And so that's kinda like how all that stuff sorta works. So you kinda get this o o ish feel without exactly being o o, if that'll make sense. Seems very familiar to the way that the goal works as well
1:12:31 with Definitely. Go is very similar in this regard for sure. And, traits are what we call interfaces in Go. So that has a very similar syntax where you say, emple trait for package instead of just emple package, and that's how you'd implement an interface. And it feels very similar where you would take interfaces as arguments and, you know, then you can pass in any structure that implements the interface and do all that kind of thing. Nice. Okay. I think we'll leave it there rather than trying to rush through anything else in a in a in a matter of a few
1:13:03 Wrap-up and Resources
1:13:06 minutes. So let's remove the screen. If anyone has any questions, feel free. We'll give you a minute to drop them into the chat, and we can just quickly talk for a second. Yeah. So, you know, I think Rust should hopefully feel familiar enough to people that come from other sea based languages. You know, there are a few quirks that have to be learned as I'm sure with all languages for sure. Yeah. And we've got an example here of Rustlings, and obviously, you've got your book, the Rust programming book. Are there any other resources you would recommend for people
1:13:39 to check out? Definitely. So we have there's multiple discords that you can join for getting help in a live chat environment as opposed to, you know, posting things. There's also the user forum at users.rustlang.org where you can ask questions, if you prefer a forum to a Discord. And those are both really great resources for getting going. Other one I would say, and this kind of an interesting trick is there's been a lot of people who learn Rust to try it once and get frustrated and say, this doesn't make any sense to me. And then they leave for six months, and
1:14:10 they come back and they try it again. And they're like, this makes perfect sense. Why did I get frustrated the first time? And so, you know, you should give Rust a try. And if if it's not for you, that's totally fine. Maybe it never will be. But also, you know, just try giving it a while and coming back. Sometimes I haven't figured out, like, this is, like, really if I could figure out what it is that happens in those months and, like, get people to understand it immediately, like, I would do it. But sometimes you just need
1:14:34 to, like, take a step away. It's kinda like that old programmer advice of, like, go on a walk or take a shower or do something else and, like, eventually the answer kinda comes to you. We found that that really happens with learning Rust a lot. Like, people will try it, be like, this is too hard. I don't understand anything. I'm gonna quit. And then they come back and they're like, this makes sense. And sometimes it takes a couple tries. We've had people say, oh, yeah. Had to give it three or four tries before it made sense, but now it
1:14:57 makes perfect sense. And so so yeah. I don't know. But that's also the other bit of advice I would give you is take advantage of the fact that the community exists and loves answering questions. Please post questions and get help if you want. And, you know, if you don't like Rust, that's totally fine. Maybe someday you'll like better. Maybe maybe not. Like, there's lots of programming languages when they have so much time. So, you know, it's it's cool. Yeah. I think that's one of my problems is that I'm too busy playing with random esoteric languages instead of actually building anything useful
1:15:24 in one language. Totally. Yeah. Jump in between. There's just too many good things out there. Know, there's Rust that I wanna get better at. There's pony that I wanna get better at. There's zigs that I wanna get better at. And I'm just like, I wanna play with all these things. It's definitely not enough time in the day. No. No. Definitely not. Alright. So we got a couple of things here. SD said lovely session. Thank you very Rod asked a question which I'll rephrase slightly. Yeah. Has the future of Rust secure with the recently offset Mozilla?
1:15:46 Discussion: Future of Rust
1:15:50 Yeah. So there is about 200 people that work on Rust in general. And at the time of the Mozilla layoffs, like, before the layoffs happened, only four or five of those people were employed by Mozilla. So I it's always tricky to answer this question because those are my friends and former colleagues. And so I don't wanna say they don't matter because they do matter because they are wonderful people and do a lot of work in Rust. But at the same time, they're a small number of a large group of people, and so the overall movement of Rust is not really
1:16:21 affected by the Mozilla layoffs. Additionally, you'll have seen and you will see in the future more and more companies picking up, getting into Rust development. So the big announcement in the last week is Amazon is, like, explicitly hiring a bunch of people to work on Rust itself. And so we're seeing other companies pick up where Mozilla left off even though, like, as I said before, most of the Rust development was volunteer in the first place. So it it affects us in the sense that, you know, some people have had to shift around and some people still work on Rust,
1:16:53 but only in a spare time capacity instead of a full time one like they used to. And some people have just found jobs other places working on Rust. And so, you know but definitely, like, the future is bright and the situation with Mozilla is pretty independent from the situation of Rust these days. Yeah. Yeah. I mean, I I can't add any more flavor to that other than what you have said. But I I can say from the cloud native perspective, which is where my, you know as the community I'm most involved in, is all these companies are now adopting
1:17:19 Rust for all sorts of crazy technology. And I think there's definitely enough enough people contribute in in that space that Rust would definitely have a future regardless of what happens in this area. And I also foundation is maybe what you're about to say. The other part I didn't say is we're working on starting a Rust foundation, and so you'll hear some news about that in the coming months. And so that's also kind of, you know, a part of that future too. Yeah. All sorts of things going on there. And there was news last week about several
1:17:46 being handed over to the Linux Foundation, which I'm sure are are probably a key component of the Rust Foundation work too, hopefully. So we'll see. I wouldn't be worried. So Rod said, thank you. And finally, I'll finish with SD saying, hey, Steve, you need to come back so we can do intermediate Rust. Sure. Yeah. Sounds good. I wouldn't make him commit on air. Don't sorry. But we'll speak afterwards. Regardless of Steve's availability, I do plan on doing more Rust content and hopefully Steve can be a part of that too. Thank you very much for your time today.
1:17:57 Conclusion and Farewell
1:18:14 That was that was awesome. I think, you know, we man hopefully covered enough of the basics that people can get started. If you've tried it before, definitely give it another try. As we said, you know, sometimes you just have to try it twice like olives. Totally. And I hope you have a great rest of your day. Thank you again for joining me and I'll speak to soon. Yeah. You too. Thanks for having me. Yeah. Thanks a lot. Bye.
Technologies featured
Meet the Cast
Stay ahead in cloud native
Tutorials, deep dives, and curated events. No fluff.
Comments