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