Reputation: 839
I'm working through the Rust documentation (book) and am confused about it's use of semicolons to separate statements.
In one example it uses the println!
macro as a statement terminated by a semicolon:
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y);
if ordering == Ordering::Less {
println!("less");
} else if ordering == Ordering::Greater {
println!("greater");
} else if ordering == Ordering::Equal {
println!("equal");
}
}
And when using the match
expression to simplify it...
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
match cmp(x, y) {
Ordering::Less => println!("less"),
Ordering::Greater => println!("greater"),
Ordering::Equal => println!("equal"),
}
}
The semicolons are gone, indicating that println!
is not a statement, but an expression in this context. I don't understand why... what am I missing?
Upvotes: 3
Views: 926
Reputation:
println!()
is a macro expanding to an expression. It has no useful return value, but it is an expression (mostly because almost everything is an expression, including function calls and blocks).
There is a convention — I don't know how common it is, but I for one follow it — to treat ()
-producing function calls as pseudo-statements, used only for their side effects, and hence terminate them with a semicolon even when not strictly necessary. This is done in the first snippet.
In the second snippet, we have a match
, and match arms expect an expression. One can use a block (Ordering::Less => { println!("less"); }
) but this is quite a bit of syntactic noise just to make extra clear that the arms are used for their side effects, so I suppose the author just left it off.
Upvotes: 7