What is the difference between having and not having a semicolon?
In Rust, almost everything is an expression. This means that almost everything returns a value. One exception is the variable binding statement let. In a let statement, and many others, the ending semicolon is a mandatory part of the syntax.
However, in expressions, the semicolon has a double role: it throws away a return value of the expression in addition to allowing further expressions. So if the expression is the last in a block, having a semicolon there means that the last value is thrown away, and not having a semicolon there means to return the last value.
An example should make it clear:
// 04/semicolon_block/src/main.rs fn main()
{
let x = 5u32;
let y =
{
let x_squared = x * x;
let x_cube = x_squared * x;
x_cube + x_squared + x
};
let z =
{
2 * x;
};
println!("x is {:?}", x);
println!("y is {:?}", y);
println!("z is {:?}", z);
}
We have two different uses of the semicolon. Let's look at the let y line first:
let y =
{
let x_squared = x * x;
let x_cube = x_squared * x;
x_cube + x_squared + x // no semi-colon
};
This code does the following:
The code within the braces is processed
The final line, without the semicolon, is assigned to y
Essentially, this is considered as an inline function that returns the line without the semicolon into the variable.
The second line to consider is for z:
let z =
{
2 * x;
};
Again, the code within the braces is evaluated. In this case, the line ends with a semicolon, so the result is thrown away and the empty value () gets bound to z.
When it is executed, we will get the following results:
In the code example, the line within fn main calling recurse gives the same result with or without the semicolon, because the Rust runtime doesn't use main's return value for anything.