]> git.proxmox.com Git - rustc.git/blame - src/doc/book/src/ch03-03-how-functions-work.md
New upstream version 1.58.1+dfsg1
[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
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
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.
38First, the “Hello, world!” message prints, and then `another_function` is
39called and its message is printed.
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
13cf67c4
XL
67`println!` macro puts `5` where the pair of curly brackets were in the format
68string.
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
94222f64 73the code to figure out what type you mean.
13cf67c4 74
3c0e092e
XL
75When defining multiple parameters, separate the parameter declarations with
76commas, like this:
13cf67c4
XL
77
78<span class="filename">Filename: src/main.rs</span>
79
80```rust
74b04a01 81{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs}}
13cf67c4
XL
82```
83
94222f64
XL
84This example creates a function named `print_labeled_measurement` with two
85parameters. The first parameter is named `value` and is an `i32`. The second is
86named `unit_label` and is type `char`. The function then prints text containing
87both the `value` and the `unit_label`.
13cf67c4
XL
88
89Let’s try running this code. Replace the program currently in your *functions*
90project’s *src/main.rs* file with the preceding example and run it using `cargo
91run`:
92
f035d41b 93```console
74b04a01 94{{#include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/output.txt}}
13cf67c4
XL
95```
96
94222f64
XL
97Because we called the function with `5` as the value for `value` and `'h'` as
98the value for `unit_label`, the program output contains those values.
13cf67c4 99
3c0e092e 100### Statements and Expressions
13cf67c4
XL
101
102Function bodies are made up of a series of statements optionally ending in an
3c0e092e
XL
103expression. So far, the functions we’ve covered haven’t included an ending
104expression, but you have seen an expression as part of a statement. Because
105Rust is an expression-based language, this is an important distinction to
106understand. Other languages don’t have the same distinctions, so let’s look at
107what statements and expressions are and how their differences affect the bodies
108of functions.
13cf67c4 109
3c0e092e
XL
110*Statements* are instructions that perform some action and do not return a
111value. *Expressions* evaluate to a resulting value. Let’s look at some examples.
13cf67c4 112
3c0e092e
XL
113We’ve actually already used statements and expressions. Creating a variable and
114assigning a value to it with the `let` keyword is a statement. In Listing 3-1,
115`let y = 6;` is a statement.
13cf67c4
XL
116
117<span class="filename">Filename: src/main.rs</span>
118
119```rust
74b04a01 120{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-01/src/main.rs}}
13cf67c4
XL
121```
122
123<span class="caption">Listing 3-1: A `main` function declaration containing one statement</span>
124
125Function definitions are also statements; the entire preceding example is a
126statement in itself.
127
128Statements do not return values. Therefore, you can’t assign a `let` statement
129to another variable, as the following code tries to do; you’ll get an error:
130
131<span class="filename">Filename: src/main.rs</span>
132
133```rust,ignore,does_not_compile
74b04a01 134{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/src/main.rs}}
13cf67c4
XL
135```
136
137When you run this program, the error you’ll get looks like this:
f035d41b
XL
138
139```console
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
94222f64
XL
149Expressions evaluate to a value and make up most of the rest of the code that
150you’ll write in Rust. Consider a math operation, such as `5 + 6`, which is an
151expression that evaluates to the value `11`. Expressions can be part of
13cf67c4
XL
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
3c0e092e
XL
154expression. Calling a macro is an expression. A new scope block created with
155curly brackets is an expression, for example:
13cf67c4
XL
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`
3c0e092e
XL
173as part of the `let` statement. Note that the `x + 1` line doesn’t have a
174semicolon at the end, unlike most of the lines you’ve seen so far. Expressions
175do not include ending semicolons. If you add a semicolon to the end of an
176expression, you turn it into a statement, and it will then not return a value.
13cf67c4
XL
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
f035d41b 200```console
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
f035d41b 238```console
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 `()`,
94222f64 245the unit type. 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.