Function bodies are made up of a series of statements optionally ending in an expression. So far, we've only covered funtions without an ending expression, but we have seen an expression as part of a statement. Because Rust is an expression-based language, this is an important distinction to understand. Other languages doesn't have the same distinctions, so let's look at what statements and expressions are and how their differences affect the bodies of functions.
We've actually already used statements and expressions. Statements are intructions that perform some action and do not return a value. Expressions evaluate to a resulting value. Let's look at some examples. Now, we'll create a variable and assigning a value to it with let keyword.
fn main(){
let y = 6;
}
Function definitions are also statemetns, the entire preceding example is a statement in itself. Statements do not return a values. Therefore, we can't assign a let statement to another variable, as the following code to tries to do; we'll get an error.
fn main(){
let x = (let y = 6);
}
The let y = 6 statement does not return a value, so there isn't anything for x to bind to. This different from what happens in other languages, such C or Ruby. In those languages we can write x = y = 6 and have both x and y have value 6. That isn't the case in Rust.
Expressions evaluate to something and make up most of the rest of the code that we'll write in Rust. Consider a simple math operation, such as 6 + 7, which is an expression that evaluates to the value 13. Expressions can be part of statements. Calling a function is an expression, calling macro is an expression. The block that we use to create new scopes, {}, is an expression. For example :
fn main(){
let x = 5;
let y = {
let x = 3;
x + 1
};
println!("The value of y is {} : ", y);
}
This expression :
{
let x = 3;
x + 1;
}
is a block that, in this case evalueates to 4. That value gets bound to y as part of the let statement. Note! That x + 1 line without a semicolon at the end, which is an unlike most of the lines we've seen so far. Expressions do not include endings semicolon. If we add a semicolon to the end of an expression, we turn it into statement, which will then not return a value. Keep this in mind as we explore funtion return values and expressions next.
Functions with Return Value
Functions also can values to the code that calls them. We don't name return values, but we do declare their type after an arrow ( -> ). In Rust, the return value of the function is synonimous with the value of the final expression in the block of the body of a function. We can return early from a function by using the return keyword and specifying a value, but most functions return the last expression implicitly. Here's an example of a function that returns a value :
fn five() -> i32 {
5
}
fn main() {
let x = five();
println!("The value of x is {}", x);
}
There are no function calls, macros, or even let statements in the five() function- just the number 5 by itself. That's a perfectly valid function in Rust. Note! That the function's return type is specified too as -> i32.
The 5 in five is the function's return value, which is why retun type is i32. Let's examine this in more detail. There are two important bits, first; the line let x = five() shows that we're using the return value of a function to initialize a variable. Because the function five return a 5, that line is the same as the following :
let x = 5;
Second, the five function has no parameters and defines the type of the return value, but the body of the function is a lonely 5 with no semicolon because it's an expression whose value we want to return. Let's look at another example :
fn main() {
let x = plus_one(5);
println!("The value of x is {}", x);
}
fn plus_one(x: i32) -> i32 {
x + 1
}
Running this code will print The value of x is 6. But if we place a semicolon at the end of the line containing x + 1, changing it from an expression to a statement and we'll get error.
The main message error is missmatched types reveals the core issue with this code. The definition of the function plus_one says that it will return an i32 but the statements don't evaluate to a value, which is expressed by (), the empty tuple. Therefore, nothing is returned, which contradicts the function definition and results in an error. In this output, Rust provides a message to possibly help rectify this issue: it suggest removing the semicolon which would fix the error.
So, maybe enaugh for now guys... Selamat belajar!!!
Wassalamu'alaikum wr. wb
Tags:
Rust