What are Function Parameters in Rust?
Function parameters are variables declared in the function’s definition to accept values when the function is called. Parameters make functions more versatile by enabling them to work with different inputs.
Syntax of Function Parameters
Here’s the general syntax for defining parameters in Rust:
fn function_name(parameter_name: data_type) {
// Function body
}
- parameter_name: Name of the parameter (follows snake_case convention).
- data_type: The type of the parameter, such as i32, f64 or String.
You can define multiple parameters separated by commas.
Examples of Function Parameters
Example 1: Single Parameter
fn greet(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
greet("Alice");
}
Output:
Hello, Alice!
In this example:
- The name parameter is a string slice (&str).
- When calling greet, the string “Alice” is passed as an argument.
Example 2: Multiple Parameters
fn add(a: i32, b: i32) {
println!("The sum is: {}", a + b);
}
fn main() {
add(5, 10);
}
Output:
The sum is: 15
Here, the function add takes two i32 parameters, a
and b
, and prints their sum.
Passing Parameters by Value
By default, parameters in Rust are passed by value, meaning the function gets a copy of the argument. Changes made to the parameter inside the function do not affect the original value.
Example 3: Pass by Value
fn increment(num: i32) {
println!("Inside the function: {}", num + 1);
}
fn main() {
let x = 10;
increment(x);
println!("Outside the function: {}", x);
}
Output:
Inside the function: 11
Outside the function: 10
The value of x remains unchanged because the parameter num is a copy.
Passing Parameters by Reference
To modify the original value, you can pass parameters by reference using &
. This allows the function to borrow the value without taking ownership.
Example 4: Pass by Reference
fn double_value(num: &mut i32) {
*num *= 2; // Dereference to modify the original value
}
fn main() {
let mut x = 5;
double_value(&mut x);
println!("Doubled value: {}", x);
}
Output:
Doubled value: 10
- The &mut keyword indicates a mutable reference, allowing the function to change the original value.
Default Parameter Values
Rust does not natively support default parameter values. However, you can achieve similar behavior using optional parameters with Option<T>
or function overloading.
Example 5: Simulating Default Parameters
fn display_message(msg: Option<&str>) {
let message = msg.unwrap_or("Default message");
println!("{}", message);
}
fn main() {
display_message(Some("Hello, Rust!"));
display_message(None);
}
Output:
Hello, Rust!
Default message
Using Tuples for Multiple Outputs
While functions can only return one value, you can use tuples to return multiple values. Parameters can also be passed as tuples.
Example 6: Passing a Tuple
fn calculate(a: i32, b: i32) -> (i32, i32) {
(a + b, a * b)
}
fn main() {
let (sum, product) = calculate(3, 4);
println!("Sum: {}, Product: {}", sum, product);
}
Output:
Sum: 7, Product: 12
Parameter Lifetimes
When dealing with references as parameters, you might need to specify lifetimes to ensure safety.
Example 7: Lifetime Annotation
fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
if s1.len() > s2.len() {
s1
} else {
s2
}
}
fn main() {
let str1 = "Rust";
let str2 = "Programming";
let result = longest(str1, str2);
println!("The longest string is: {}", result);
}
Output:
The longest string is: Programming
Here, the lifetime ‘a ensures that the returned reference is valid as long as both input references are valid.
Variadic Parameters
Rust does not natively support variadic parameters (functions accepting a variable number of arguments). However, you can achieve similar functionality using slices.
Example 8: Variadic-Like Behavior
fn sum_all(numbers: &[i32]) -> i32 {
numbers.iter().sum()
}
fn main() {
let nums = [1, 2, 3, 4, 5];
println!("The sum is: {}", sum_all(&nums));
}
Output:
The sum is: 15