]> git.proxmox.com Git - rustc.git/blob - src/doc/book/second-edition/src/ch03-03-how-functions-work.md
New upstream version 1.23.0+dfsg1
[rustc.git] / src / doc / book / second-edition / src / ch03-03-how-functions-work.md
1 ## How Functions Work
2
3 Functions are pervasive in Rust code. You’ve already seen one of the most
4 important functions in the language: the `main` function, which is the entry
5 point of many programs. You’ve also seen the `fn` keyword, which allows you to
6 declare new functions.
7
8 Rust code uses *snake case* as the conventional style for function and variable
9 names. In snake case, all letters are lowercase and underscores separate words.
10 Here’s a program that contains an example function definition:
11
12 <span class="filename">Filename: src/main.rs</span>
13
14 ```rust
15 fn main() {
16 println!("Hello, world!");
17
18 another_function();
19 }
20
21 fn another_function() {
22 println!("Another function.");
23 }
24 ```
25
26 Function definitions in Rust start with `fn` and have a set of parentheses
27 after the function name. The curly brackets tell the compiler where the
28 function body begins and ends.
29
30 We can call any function we’ve defined by entering its name followed by a set
31 of parentheses. Because `another_function` is defined in the program, it can be
32 called from inside the `main` function. Note that we defined `another_function`
33 *after* the `main` function in the source code; we could have defined it before
34 as well. Rust doesn’t care where you define your functions, only that they’re
35 defined somewhere.
36
37 Let’s start a new binary project named *functions* to explore functions
38 further. Place the `another_function` example in *src/main.rs* and run it. You
39 should see the following output:
40
41 ```text
42 $ cargo run
43 Compiling functions v0.1.0 (file:///projects/functions)
44 Finished dev [unoptimized + debuginfo] target(s) in 0.28 secs
45 Running `target/debug/functions`
46 Hello, world!
47 Another function.
48 ```
49
50 The lines execute in the order in which they appear in the `main` function.
51 First, the “Hello, world!” message prints, and then `another_function` is
52 called and its message is printed.
53
54 ### Function Parameters
55
56 Functions can also be defined to have *parameters*, which are special variables
57 that are part of a function’s signature. When a function has parameters, we can
58 provide it with concrete values for those parameters. Technically, the concrete
59 values are called *arguments*, but in casual conversation people tend to use
60 the words “parameter” and “argument” interchangeably for either the variables
61 in a function’s definition or the concrete values passed in when you call a
62 function.
63
64 The following rewritten version of `another_function` shows what parameters
65 look like in Rust:
66
67 <span class="filename">Filename: src/main.rs</span>
68
69 ```rust
70 fn main() {
71 another_function(5);
72 }
73
74 fn another_function(x: i32) {
75 println!("The value of x is: {}", x);
76 }
77 ```
78
79 Try running this program; you should get the following output:
80
81 ```text
82 $ cargo run
83 Compiling functions v0.1.0 (file:///projects/functions)
84 Finished dev [unoptimized + debuginfo] target(s) in 1.21 secs
85 Running `target/debug/functions`
86 The value of x is: 5
87 ```
88
89 The declaration of `another_function` has one parameter named `x`. The type of
90 `x` is specified as `i32`. When `5` is passed to `another_function`, the
91 `println!` macro puts `5` where the pair of curly brackets were in the format
92 string.
93
94 In function signatures, you *must* declare the type of each parameter. This is
95 a deliberate decision in Rust’s design: requiring type annotations in function
96 definitions means the compiler almost never needs you to use them elsewhere in
97 the code to figure out what you mean.
98
99 When you want a function to have multiple parameters, separate the parameter
100 declarations with commas, like this:
101
102 <span class="filename">Filename: src/main.rs</span>
103
104 ```rust
105 fn main() {
106 another_function(5, 6);
107 }
108
109 fn another_function(x: i32, y: i32) {
110 println!("The value of x is: {}", x);
111 println!("The value of y is: {}", y);
112 }
113 ```
114
115 This example creates a function with two parameters, both of which are `i32`
116 types. The function then prints out the values in both of its parameters. Note
117 that function parameters don’t all need to be the same type, they just happen
118 to be in this example.
119
120 Let’s try running this code. Replace the program currently in your *functions*
121 project’s *src/main.rs* file with the preceding example, and run it using
122 `cargo run`:
123
124 ```text
125 $ cargo run
126 Compiling functions v0.1.0 (file:///projects/functions)
127 Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
128 Running `target/debug/functions`
129 The value of x is: 5
130 The value of y is: 6
131 ```
132
133 Because we called the function with `5` as the value for `x` and `6` is passed
134 as the value for `y`, the two strings are printed with these values.
135
136 ### Function Bodies
137
138 Function bodies are made up of a series of statements optionally ending in an
139 expression. So far, we’ve only covered functions without an ending expression,
140 but we have seen expressions as parts of statements. Because Rust is an
141 expression-based language, this is an important distinction to understand.
142 Other languages don’t have the same distinctions, so let’s look at what
143 statements and expressions are and how their differences affect the bodies of
144 functions.
145
146 ### Statements and Expressions
147
148 We’ve actually already used statements and expressions. *Statements* are
149 instructions that perform some action and do not return a value. *Expressions*
150 evaluate to a resulting value. Let’s look at some examples.
151
152 Creating a variable and assigning a value to it with the `let` keyword is a
153 statement. In Listing 3-1, `let y = 6;` is a statement:
154
155 <span class="filename">Filename: src/main.rs</span>
156
157 ```rust
158 fn main() {
159 let y = 6;
160 }
161 ```
162
163 <span class="caption">Listing 3-1: A `main` function declaration containing one statement.</span>
164
165 Function definitions are also statements; the entire preceding example is a
166 statement in itself.
167
168 Statements do not return values. Therefore, you can’t assign a `let` statement
169 to another variable, as the following code tries to do; you’ll get an error:
170
171 <span class="filename">Filename: src/main.rs</span>
172
173 ```rust,ignore
174 fn main() {
175 let x = (let y = 6);
176 }
177 ```
178
179 When you run this program, the error you’ll get looks like this:
180
181 ```text
182 $ cargo run
183 Compiling functions v0.1.0 (file:///projects/functions)
184 error: expected expression, found statement (`let`)
185 --> src/main.rs:2:14
186 |
187 2 | let x = (let y = 6);
188 | ^^^
189 |
190 = note: variable declaration using `let` is a statement
191 ```
192
193 The `let y = 6` statement does not return a value, so there isn’t anything for
194 `x` to bind to. This is different than in other languages, such as C and Ruby,
195 where the assignment returns the value of the assignment. In those languages,
196 you can write `x = y = 6` and have both `x` and `y` have the value `6`; that is
197 not the case in Rust.
198
199 Expressions evaluate to something and make up most of the rest of the code that
200 you’ll write in Rust. Consider a simple math operation, such as `5 + 6`, which
201 is an expression that evaluates to the value `11`. Expressions can be part of
202 statements: in Listing 3-1 that had the statement `let y = 6;`, `6` is an
203 expression that evaluates to the value `6`. Calling a function is an
204 expression. Calling a macro is an expression. The block that we use to create
205 new scopes, `{}`, is an expression, for example:
206
207 <span class="filename">Filename: src/main.rs</span>
208
209 ```rust
210 fn main() {
211 let x = 5;
212
213 let y = {
214 let x = 3;
215 x + 1
216 };
217
218 println!("The value of y is: {}", y);
219 }
220 ```
221
222 This expression:
223
224 ```rust,ignore
225 {
226 let x = 3;
227 x + 1
228 }
229 ```
230
231 is a block that, in this case, evaluates to `4`. That value gets bound to `y`
232 as part of the `let` statement. Note the `x + 1` line without a semicolon at
233 the end, unlike most of the lines you’ve seen so far. Expressions do not
234 include ending semicolons. If you add a semicolon to the end of an expression,
235 you turn it into a statement, which will then not return a value. Keep this in
236 mind as you explore function return values and expressions next.
237
238 ### Functions with Return Values
239
240 Functions can return values to the code that calls them. We don’t name return
241 values, but we do declare their type after an arrow (`->`). In Rust, the return
242 value of the function is synonymous with the value of the final expression in
243 the block of the body of a function. You can return early from a function by
244 using the `return` keyword and specifying a value, but most functions return
245 the last expression implicitly. Here’s an example of a function that returns a
246 value:
247
248 <span class="filename">Filename: src/main.rs</span>
249
250 ```rust
251 fn five() -> i32 {
252 5
253 }
254
255 fn main() {
256 let x = five();
257
258 println!("The value of x is: {}", x);
259 }
260 ```
261
262 There are no function calls, macros, or even `let` statements in the `five`
263 function—just the number `5` by itself. That’s a perfectly valid function in
264 Rust. Note that the function’s return type is specified, too, as `-> i32`. Try
265 running this code; the output should look like this:
266
267 ```text
268 $ cargo run
269 Compiling functions v0.1.0 (file:///projects/functions)
270 Finished dev [unoptimized + debuginfo] target(s) in 0.30 secs
271 Running `target/debug/functions`
272 The value of x is: 5
273 ```
274
275 The `5` in `five` is the function’s return value, which is why the return type
276 is `i32`. Let’s examine this in more detail. There are two important bits:
277 first, the line `let x = five();` shows that we’re using the return value of a
278 function to initialize a variable. Because the function `five` returns a `5`,
279 that line is the same as the following:
280
281 ```rust
282 let x = 5;
283 ```
284
285 Second, the `five` function has no parameters and defines the type of the
286 return value, but the body of the function is a lonely `5` with no semicolon
287 because it’s an expression whose value we want to return. Let’s look at another
288 example:
289
290 <span class="filename">Filename: src/main.rs</span>
291
292 ```rust
293 fn main() {
294 let x = plus_one(5);
295
296 println!("The value of x is: {}", x);
297 }
298
299 fn plus_one(x: i32) -> i32 {
300 x + 1
301 }
302 ```
303
304 Running this code will print `The value of x is: 6`. What happens if we place a
305 semicolon at the end of the line containing `x + 1`, changing it from an
306 expression to a statement? We’ll get an error:
307
308 <span class="filename">Filename: src/main.rs</span>
309
310 ```rust,ignore
311 fn main() {
312 let x = plus_one(5);
313
314 println!("The value of x is: {}", x);
315 }
316
317 fn plus_one(x: i32) -> i32 {
318 x + 1;
319 }
320 ```
321
322 Running this code produces an error, as follows:
323
324 ```text
325 error[E0308]: mismatched types
326 --> src/main.rs:7:28
327 |
328 7 | fn plus_one(x: i32) -> i32 {
329 | ____________________________^
330 8 | | x + 1;
331 | | - help: consider removing this semicolon
332 9 | | }
333 | |_^ expected i32, found ()
334 |
335 = note: expected type `i32`
336 found type `()`
337 ```
338
339 The main error message, “mismatched types,” reveals the core issue with this
340 code. The definition of the function `plus_one` says that it will return an
341 `i32`, but statements don’t evaluate to a value, which is expressed by `()`,
342 the empty tuple. Therefore, nothing is returned, which contradicts the function
343 definition and results in an error. In this output, Rust provides a message to
344 possibly help rectify this issue: it suggests removing the semicolon, which
345 would fix the error.