This lesson takes an existing function with duplicated functionality and makes it more DRY by extracting core functionalities into another function.
Instructor: [00:00] To wrap it up, let's take this duplicated functionality of reading the input and parsing the value, and put it in a separate function. For that, we go ahead and create a function, readUserInput(), which will return a number. Then, we just take one of our input functionalities, copy it over, and make it a little bit more generic.
[00:30] We don't need this. Let's call this one input instead, change it here as well. Our variable is now going to be a digit. This is going to be input, this is going to be digit. Last but not least, we need to return the digit.
[00:49] A little bit of formatting, and then we can go ahead and make use of that function by saying, let a = readUserInput(). Then, we get rid of this. We can do exactly the same for our variable b, copy this over here, "Please enter the first number," and there we have our optimized program.
[01:20] This should work the same way as before, so if we do cargo run, we can enter a first number and a second number. It still works. It still keeps us asking. That's how you make your code a bit more dry.
Hey Matt,
Interesting, so I see the return keyword can be implied at the end of a function (or block?), as demonstrated in read_user_input. I guess that's been true in the sum function as well.
So the rule is:
Every line inside a function that ends with a ;
is a statement and if it's the last line of a function body and it doesn't end with a ;
it'll return the value of that line's expression.
So yes:
fn sum(a: i32, b: i32) -> i32 {
a + b
}
^ Therefore returns whatever that last line in the function body evaluates to. However, it's still possible to use explicit return
statements, in fact it's needed if you want to return earlier inside a function body.
similar to ES6 JavaScript in that you can dispense with the curly braces when using its fat arrow and only returning a single statement, e.g. const myFunc = (a, b) => a + b).
This is correct. A match
branch that is a single-line statement/expression can be written as:
Ok(val) => { some_expr }
Or
Ok(val) => some_expr
Generally, I'd recommend to use as little symbols/characters to express the same thing as possible unless readability suffers from it.
i'm curious as to why you can pass a and b to sum but it doesn't move them like the other function did, so that you're still able to pass a and b into println!() without them being & references.
i'm also curious as to why you have to say "Pascal".to_string() when assigning the name....is "Pascal" by itself not a string already?
Hey Colin!
i'm curious as to why you can pass a and b to sum but it doesn't move them like the other function did, so that you're still able to pass a and b into println!() without them being & references.
Excellent question. So the reason there's actually no move happening is because... Rust will only not move values that are either a) primitives that don't require heap allocation (e.g. numbers, those just end up on the stack) or b) types that implement the Copy
trait.
i'm also curious as to why you have to say "Pascal".to_string() when assigning the name....is "Pascal" by itself not a string already?
Not exactly. In Rust there can be values of type String
, &String
, &str
and then there's also str
, but the last one is usually only accessible via a reference (so &str
).
I didn't want to go into that in this lesson because it'll require better understanding of how Rust manages memory as well as ownershiip.
I wrote an article to explain this for now: https://blog.thoughtram.io/string-vs-str-in-rust/
@Colin thanks for these questions, these were the same questions I had. @Pascal, thanks a huge lot for answering in such detail and sharing the artical about strings.
Interesting, so I see the
return
keyword can be implied at the end of a function (or block?), as demonstrated inread_user_input
. I guess that's been true in thesum
function as well.I noticed you changed the
Ok
function fromOk(val) => { digit = val; }
toOk(val) => digit = val,
; I also noticed that the trailing comma wasn't required in the first instance but appears to be in the second. What are the rules for this stuff? I'm guessing these are yet more signals to the compiler (and that it's similar to ES6 JavaScript in that you can dispense with the curly braces when using its fat arrow and only returning a single statement, e.g.const myFunc = (a, b) => a + b
).Thanks for the great course! Looking forward to more guidance on Rust.