Functions

(And a little bit on function-like macros)

Rust functions are private by default, and are defined with the keyword fn:

The keyword pub must be used before fn in order to make a function public, and therefore accessible in other Rust programs.


    

Every Rust program needs a main function, which contains the only part of the program that will be executed. All other separately defined functions need to be included, or called, inside this function:


    

Rust functions can implicitly return the last found value in the function body as an expression, as long as the return value is explicitly typed:

error[E0277]: `()` doesn't implement `std::fmt::Display`
--> src/main.rs:2:20
|
2 | println!("{}", character())
| `()` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `()`

error[E0308]: mismatched types
--> src/main.rs:6:5
|
5 | fn character() {
| - help: try adding a return type: `-> char`
6 | 'f' // Return value of function without semicolon
| ^^^ expected `()`, found `char`

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.

Because the return value wasn't explicitly given for the character() function, and because it's trying to return an expression, the function returned the empty unit type, defined as ().

In Rust, the results of functions can immediately be assigned to variables:


    

Functions can be written to take parameters, variables defined in the brackets next to the function name that can then be used in the body of a function:

Function parameters always need explicit type definitions.


    

Note the syntax between the curly brackets in the string formatting of the println!() call in the above example. This prints the result of the supplied function call in a debug view, allowing for the printing of data structures like structs, enums and tuples (explained later).

Exercise:
Add a function below named num that takes a u32 and returns it unchanged, without using the return keyword:


    

Functions can also be implemented on structs and enums, as methods, with the impl keyword:


    

The syntax involving the ampersand symbol (&) in the above example will be fully explained in the next chapter. For now, note that in order for the Train struct t to access its own fields, it has to get them using the self keyword. This allows structs and enums to refer to themselves in their methods, and perform actions like calling other functions and methods on themselves.

As mentioned before, println!() is not a function, but a macro.

Function-like macros, explained very briefly, are part of a larger, much more complicated collection of functionality in the Rust language.

They appear to be normal functions, except for the exclamation point used in their names:

The above examples of Rust macros are all built into the standard library.

The main feature that sets function-like macros apart from functions is that macros can take variable numbers of arguments as input: