📌 Introduction
In programming, a function is like a “recipe”—you write a series of steps, and then you can reuse that logic by calling it. In scientific computing, many formulas and algorithms appear repeatedly, and packaging them into functions can make the code clearer and less error-prone. In fact, readers familiar with any high-level programming language should be familiar with the concept of functions. So let’s quickly look at how Rust defines functions.
đź’ˇ Key Points
1. Function Definition
Rust defines functions using <span>fn</span>:
fn add(a: i32, b: i32) -> i32 {<br /> a + b // The last line expression is the return value<br />}<br />
Key Points:
-
Parameters must specify types (e.g., a: i32).
-
The return value type is specified using ->.
-
Rust is an expression-oriented language; the last expression without a semicolon is the return value.
Regarding the last point, we will elaborate a bit. For newcomers, encountering this feature of Rust can be somewhat unfamiliar. In many languages (like C/Java), the return value of a function must be explicitly written using return; otherwise, it will result in an error. Rust differs from them; the function body itself is an expression block, and the value of the last line expression (without a semicolon!) automatically becomes the return value of the function. What if you add a semicolon to the last line? Then the expression becomes a statement, and the entire function returns a unit value: <span>()</span>.
2. Using return
Although using an expression directly is usually more concise, sometimes we need to exit the function early.
fn divide(a: i32, b: i32) -> i32 {<br /> if b == 0 {<br /> println!("Cannot divide by 0!");<br /> return 0; // Early return<br /> }<br /> a / b<br />}<br />
Therefore, you can remember a little tip:
-
General case → Use the last expression as the return value for conciseness.
-
Special cases (errors, early exits) → Use return to interrupt function execution.
🔍 Complete Code Example
Write a function fahrenheit_to_celsius that converts Fahrenheit to Celsius (a classic programming problem):
fn fahrenheit_to_celsius(f: f64) -> f64 {<br /> (f - 32.0) * 5.0 / 9.0<br />}<br /><br />fn main() {<br /> let f = 98.6;<br /> let c = fahrenheit_to_celsius(f);<br /> println!("{} Fahrenheit = {:.2} Celsius", f, c);<br />}<br />
Explanation:
Both parameters and return values use f64 floating-point numbers.
<span>(f - 32.0) * 5.0 / 9.0</span> is the last expression, directly serving as the return value.
đź§Ş Exercises Ă—3
Exercise 1: Write a function that returns the square of an integer.
Answer:
fn square(x: i32) -> i32 {<br /> x * x<br />}<br />
Exercise 2: Write a function that calculates the average of two floating-point numbers.
Answer:
fn average(a: f64, b: f64) -> f64 {<br /> (a + b) / 2.0<br />}<br />
Exercise 3: Write a function that converts minutes to hours and minutes (e.g., 125 minutes → 2 hours 5 minutes).
Answer:
fn minutes_to_hours(minutes: u32) -> (u32, u32) {<br /> (minutes / 60, minutes % 60)<br />}<br /><br />fn main() {<br /> let (h, m) = minutes_to_hours(125);<br /> println!("125 minutes = {} hours {} minutes", h, m);<br />}<br />
📚 Further Reading
Official Documentation: Rust Book – Functions
Interactive Practice: Rust by Example – Functions
âś… Summary:
-
Functions allow us to package logic for convenient reuse.
-
Rust’s function return value defaults to the last expression, making it more concise. Note! Do not add a semicolon!
-
Special cases can use return for early exits, making the syntax more intuitive.