Functions
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) { println!("In `generic`"); } // Explicitly specified type parameter `char` to `generic()`. // Note the turbofish notation ::<> fn main() { generic::<char>('a'); }
use std::fmt::Display; 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. // `t` must be some kind of (smart) pointer: &, `Rc`, `Box`... println!("{}", t); } fn main() { let s = String::from("hello"); generic(&s[..]); }
Function pointers
fn add_one(x: i32) -> i32 { x + 1 } fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { // function pointer f(arg) + f(arg) } fn main() { println!("{}", do_twice(add_one, 1)); }
Diverging functions
Diverging functions never return.
fn foo() -> ! { // ! is the Never type panic!("This call never returns."); } fn main() { println!("Will panic"); foo(); }
[functions: add desc (P1)](https://github.com/john-cd/rust_howto/issues/543)