Functions are expressions
Worked examples
Read the claim, then run it and check the machine agrees. One at a time — nothing here is taken on trust.
fn polynomial(x: f64) -> f64 {
let x2 = x * x;
3.0 * x2 - 2.0 * x + 1.0
}
fn main() {
let y = {
let x = 3;
x + 1
};
println!("block value: {y}");
println!("p(2) = {}", polynomial(2.0));
println!("p(0) = {}", polynomial(0.0));
}
The block computes 4; polynomial is the same shape with a
signature on it — one scratch binding, then a tail expression
that IS the answer (p(2) = 9, p(0) = 1). Notice what's absent:
no return, and no semicolon on the last line of either block.
That absence is doing the returning.
fn shout(name: &str) {
// no `->`: this function returns ()
println!("HELLO, {name}!");
}
fn main() {
let with_tail = { 2 + 2 };
println!("with tail: {with_tail}");
let nothing = shout("world");
println!("a unit value, debug-printed: {nothing:?}");
println!("size of (): {} bytes", std::mem::size_of::<()>());
}
shout has no ->, so it returns () — and you can even bind
that: nothing prints as () and occupies zero bytes. This is
why the semicolon error says found (): statements and
tail-less blocks all evaluate to this one, very real, very empty
value. Rust has no "void" hole in the type system — just a type
with nothing to say.
fn digits(n: u32) -> u32 {
if n == 0 {
return 1; // ilog10(0) would panic; guard it out
}
n.ilog10() + 1
}
fn min_max(a: i32, b: i32) -> (i32, i32) {
if a > b {
return (b, a); // early exit: the swapped case
}
(a, b) // tail: already in order
}
fn main() {
println!("digits(0) = {}", digits(0));
println!("digits(9) = {}", digits(9));
println!("digits(1000) = {}", digits(1000));
println!("min_max(7, 3) = {:?}", min_max(7, 3));
println!("min_max(3, 7) = {:?}", min_max(3, 7));
}
Both functions have the lesson's recommended anatomy: return
handles the case that can't fall through (zero has no logarithm —
the unguarded call panics with "argument of integer logarithm
must be positive", verified), and the main path is a bare tail
expression. Outputs: 1, 1, 4, (3, 7), (3, 7).
Check the concept
One question at a time. Unsure? Revisit the lecture, then answer.
The challenge
Pass the quiz to unlock the challenge — your code will still be waiting here.