This lesson takes an existing function with duplicated functionality and makes it more DRY by extracting core functionalities into another function.
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.
I noticed you changed the Ok
function from Ok(val) => { digit = val; }
to Ok(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.
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.