]> git.proxmox.com Git - rustc.git/blame - src/doc/book/src/ch03-03-how-functions-work.md
bump version to 1.79.0+dfsg1-1~bpo12+pve2
[rustc.git] / src / doc / book / src / ch03-03-how-functions-work.md
CommitLineData
13cf67c4
XL
1## Functions
2
94222f64 3Functions are prevalent in Rust code. You’ve already seen one of the most
13cf67c4
XL
4important functions in the language: the `main` function, which is the entry
5point of many programs. You’ve also seen the `fn` keyword, which allows you to
6declare new functions.
7
8Rust code uses *snake case* as the conventional style for function and variable
3c0e092e 9names, in which all letters are lowercase and underscores separate words.
13cf67c4
XL
10Here’s a program that contains an example function definition:
11
12<span class="filename">Filename: src/main.rs</span>
13
14```rust
74b04a01 15{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-16-functions/src/main.rs}}
13cf67c4
XL
16```
17
3c0e092e
XL
18We define a function in Rust by entering `fn` followed by a function name and a
19set of parentheses. The curly brackets tell the compiler where the function
20body begins and ends.
13cf67c4
XL
21
22We can call any function we’ve defined by entering its name followed by a set
23of parentheses. Because `another_function` is defined in the program, it can be
24called from inside the `main` function. Note that we defined `another_function`
25*after* the `main` function in the source code; we could have defined it before
26as well. Rust doesn’t care where you define your functions, only that they’re
04454e1e 27defined somewhere in a scope that can be seen by the caller.
13cf67c4
XL
28
29Let’s start a new binary project named *functions* to explore functions
30further. Place the `another_function` example in *src/main.rs* and run it. You
31should see the following output:
32
f035d41b 33```console
74b04a01 34{{#include ../listings/ch03-common-programming-concepts/no-listing-16-functions/output.txt}}
13cf67c4
XL
35```
36
37The lines execute in the order in which they appear in the `main` function.
2b03887a
FG
38First the “Hello, world!” message prints, and then `another_function` is called
39and its message is printed.
13cf67c4 40
3c0e092e 41### Parameters
13cf67c4 42
3c0e092e
XL
43We can define functions to have *parameters*, which are special variables that
44are part of a function’s signature. When a function has parameters, you can
45provide it with concrete values for those parameters. Technically, the concrete
46values are called *arguments*, but in casual conversation, people tend to use
47the words *parameter* and *argument* interchangeably for either the variables
48in a function’s definition or the concrete values passed in when you call a
49function.
13cf67c4 50
3c0e092e 51In this version of `another_function` we add a parameter:
13cf67c4
XL
52
53<span class="filename">Filename: src/main.rs</span>
54
55```rust
74b04a01 56{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs}}
13cf67c4
XL
57```
58
59Try running this program; you should get the following output:
60
f035d41b 61```console
74b04a01 62{{#include ../listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/output.txt}}
13cf67c4
XL
63```
64
65The declaration of `another_function` has one parameter named `x`. The type of
3c0e092e 66`x` is specified as `i32`. When we pass `5` in to `another_function`, the
04454e1e
FG
67`println!` macro puts `5` where the pair of curly brackets containing `x` was
68in the format string.
13cf67c4
XL
69
70In function signatures, you *must* declare the type of each parameter. This is
71a deliberate decision in Rust’s design: requiring type annotations in function
72definitions means the compiler almost never needs you to use them elsewhere in
04454e1e
FG
73the code to figure out what type you mean. The compiler is also able to give
74more helpful error messages if it knows what types the function expects.
13cf67c4 75
3c0e092e
XL
76When defining multiple parameters, separate the parameter declarations with
77commas, like this:
13cf67c4
XL
78
79<span class="filename">Filename: src/main.rs</span>
80
81```rust
74b04a01 82{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs}}
13cf67c4
XL
83```
84
94222f64
XL
85This example creates a function named `print_labeled_measurement` with two
86parameters. The first parameter is named `value` and is an `i32`. The second is
87named `unit_label` and is type `char`. The function then prints text containing
88both the `value` and the `unit_label`.
13cf67c4
XL
89
90Let’s try running this code. Replace the program currently in your *functions*
91project’s *src/main.rs* file with the preceding example and run it using `cargo
92run`:
93
f035d41b 94```console
74b04a01 95{{#include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/output.txt}}
13cf67c4
XL
96```
97
94222f64
XL
98Because we called the function with `5` as the value for `value` and `'h'` as
99the value for `unit_label`, the program output contains those values.
13cf67c4 100
3c0e092e 101### Statements and Expressions
13cf67c4
XL
102
103Function bodies are made up of a series of statements optionally ending in an
3c0e092e
XL
104expression. So far, the functions we’ve covered haven’t included an ending
105expression, but you have seen an expression as part of a statement. Because
106Rust is an expression-based language, this is an important distinction to
107understand. Other languages don’t have the same distinctions, so let’s look at
108what statements and expressions are and how their differences affect the bodies
109of functions.
13cf67c4 110
2b03887a
FG
111* **Statements** are instructions that perform some action and do not return
112 a value.
113* **Expressions** evaluate to a resultant value. Let’s look at some examples.
13cf67c4 114
3c0e092e
XL
115We’ve actually already used statements and expressions. Creating a variable and
116assigning a value to it with the `let` keyword is a statement. In Listing 3-1,
117`let y = 6;` is a statement.
13cf67c4
XL
118
119<span class="filename">Filename: src/main.rs</span>
120
121```rust
74b04a01 122{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-01/src/main.rs}}
13cf67c4
XL
123```
124
125<span class="caption">Listing 3-1: A `main` function declaration containing one statement</span>
126
127Function definitions are also statements; the entire preceding example is a
128statement in itself.
129
130Statements do not return values. Therefore, you can’t assign a `let` statement
131to another variable, as the following code tries to do; you’ll get an error:
132
133<span class="filename">Filename: src/main.rs</span>
134
135```rust,ignore,does_not_compile
74b04a01 136{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/src/main.rs}}
13cf67c4
XL
137```
138
139When you run this program, the error you’ll get looks like this:
f035d41b
XL
140
141```console
ba9703b0 142{{#include ../listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt}}
13cf67c4
XL
143```
144
145The `let y = 6` statement does not return a value, so there isn’t anything for
146`x` to bind to. This is different from what happens in other languages, such as
147C and Ruby, where the assignment returns the value of the assignment. In those
148languages, you can write `x = y = 6` and have both `x` and `y` have the value
149`6`; that is not the case in Rust.
150
94222f64
XL
151Expressions evaluate to a value and make up most of the rest of the code that
152you’ll write in Rust. Consider a math operation, such as `5 + 6`, which is an
153expression that evaluates to the value `11`. Expressions can be part of
13cf67c4
XL
154statements: in Listing 3-1, the `6` in the statement `let y = 6;` is an
155expression that evaluates to the value `6`. Calling a function is an
3c0e092e
XL
156expression. Calling a macro is an expression. A new scope block created with
157curly brackets is an expression, for example:
13cf67c4
XL
158
159<span class="filename">Filename: src/main.rs</span>
160
161```rust
74b04a01 162{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs}}
13cf67c4
XL
163```
164
165This expression:
166
167```rust,ignore
168{
169 let x = 3;
170 x + 1
171}
172```
173
174is a block that, in this case, evaluates to `4`. That value gets bound to `y`
3c0e092e 175as part of the `let` statement. Note that the `x + 1` line doesn’t have a
2b03887a
FG
176semicolon at the end, which is unlike most of the lines you’ve seen so far.
177Expressions do not include ending semicolons. If you add a semicolon to the end
178of an expression, you turn it into a statement, and it will then not return a
179value. Keep this in mind as you explore function return values and expressions
180next.
13cf67c4
XL
181
182### Functions with Return Values
183
184Functions can return values to the code that calls them. We don’t name return
a2a8927a
XL
185values, but we must declare their type after an arrow (`->`). In Rust, the
186return value of the function is synonymous with the value of the final
187expression in the block of the body of a function. You can return early from a
188function by using the `return` keyword and specifying a value, but most
189functions return the last expression implicitly. Here’s an example of a
190function that returns a value:
13cf67c4
XL
191
192<span class="filename">Filename: src/main.rs</span>
193
194```rust
74b04a01 195{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs}}
13cf67c4
XL
196```
197
198There are no function calls, macros, or even `let` statements in the `five`
199function—just the number `5` by itself. That’s a perfectly valid function in
9fa01778 200Rust. Note that the function’s return type is specified too, as `-> i32`. Try
13cf67c4
XL
201running this code; the output should look like this:
202
f035d41b 203```console
74b04a01 204{{#include ../listings/ch03-common-programming-concepts/no-listing-21-function-return-values/output.txt}}
13cf67c4
XL
205```
206
207The `5` in `five` is the function’s return value, which is why the return type
208is `i32`. Let’s examine this in more detail. There are two important bits:
209first, the line `let x = five();` shows that we’re using the return value of a
210function to initialize a variable. Because the function `five` returns a `5`,
211that line is the same as the following:
212
213```rust
214let x = 5;
215```
216
217Second, the `five` function has no parameters and defines the type of the
218return value, but the body of the function is a lonely `5` with no semicolon
219because it’s an expression whose value we want to return.
220
221Let’s look at another example:
222
223<span class="filename">Filename: src/main.rs</span>
224
225```rust
74b04a01 226{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs}}
13cf67c4
XL
227```
228
229Running this code will print `The value of x is: 6`. But if we place a
230semicolon at the end of the line containing `x + 1`, changing it from an
2b03887a 231expression to a statement, we’ll get an error:
13cf67c4
XL
232
233<span class="filename">Filename: src/main.rs</span>
234
235```rust,ignore,does_not_compile
74b04a01 236{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs}}
13cf67c4
XL
237```
238
239Compiling this code produces an error, as follows:
240
f035d41b 241```console
74b04a01 242{{#include ../listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt}}
13cf67c4
XL
243```
244
2b03887a 245The main error message, `mismatched types`, reveals the core issue with this
13cf67c4
XL
246code. The definition of the function `plus_one` says that it will return an
247`i32`, but statements don’t evaluate to a value, which is expressed by `()`,
94222f64 248the unit type. Therefore, nothing is returned, which contradicts the function
13cf67c4
XL
249definition and results in an error. In this output, Rust provides a message to
250possibly help rectify this issue: it suggests removing the semicolon, which
251would fix the error.