Functions
/// This function takes an integer `x` and a character `unit_label` as input. /// It calculates a value `y` by adding 3 to `x`. /// It then prints the value of `y` along with the `unit_label`. /// Finally, it returns the calculated value `y`. fn foo(x: i32, unit_label: char) -> i32 { let y = { let z = 3; x + z // Expression at the end of a block - no semi-colon. }; println!("The value of y is: {y}{unit_label}"); y // Returns `y` - no semi-colon. } fn main() { println!("{}", foo(1, 'm')); }
The unit type ()
(void
in some languages) is the default return type when no type is given for a function. It could be omitted: fn log(message: &str) { ... }
Generic Functions
fn generic<T>(_t: T) { // This is a generic function that can take any type. println!("In `generic`"); } // We explicitly specify the type parameter `char` for `generic()`. // Note the use of the 'turbofish' notation: `::<>` fn main() { generic::<char>('a'); }
use std::fmt::Display; // This is a generic function that can work with types that may not have a // known size at compile time. // It requires that the type `T` implements the `Display` trait, so it can // be printed. fn generic<T: ?Sized + Display>(t: &T) { // By default, generic functions will work only on types that have a // known size at compile time. Use `?Sized` to relax that rule. println!("{}", t); } fn main() { let s = String::from("hello"); generic(&s[..]); generic(&s); }
Function Pointers
/// Add one to the input. fn add_one(x: i32) -> i32 { x + 1 } /// This function takes a function pointer. fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { f(arg) + f(arg) } fn main() { println!("{}", do_twice(add_one, 1)); }
Diverging Functions
Diverging functions never return.
/// This function diverges, meaning it never returns. /// It uses the `!` (Never) type to indicate this. fn foo() -> ! { panic!("This call never returns."); } fn main() { println!("Will panic"); foo(); }
Related Topics
- Closures.
- Rust Patterns.