]>
Commit | Line | Data |
---|---|---|
cc61c64b XL |
1 | |
2 | [TOC] | |
3 | ||
7cac9316 | 4 | # Using Modules to Reuse and Organize Code |
cc61c64b XL |
5 | |
6 | When you start writing programs in Rust, your code might live solely in the | |
7cac9316 XL |
7 | `main` function. As your code grows, you’ll eventually move functionality into |
8 | other functions for reuse and better organization. By splitting your code into | |
9 | smaller chunks, each chunk is easier to understand on its own. But what happens | |
10 | if you have too many functions? Rust has a module system that enables the reuse | |
11 | of code in an organized fashion. | |
cc61c64b XL |
12 | |
13 | In the same way that you extract lines of code into a function, you can extract | |
7cac9316 | 14 | functions (and other code, like structs and enums) into different modules. A |
cc61c64b XL |
15 | *module* is a namespace that contains definitions of functions or types, and |
16 | you can choose whether those definitions are visible outside their module | |
17 | (public) or not (private). Here’s an overview of how modules work: | |
18 | ||
7cac9316 | 19 | * The `mod` keyword declares a new module. Code within the module appears |
abe05a73 | 20 | either immediately following this declaration within curly brackets or in |
7cac9316 XL |
21 | another file. |
22 | * By default, functions, types, constants, and modules are private. The `pub` | |
23 | keyword makes an item public and therefore visible outside its namespace. | |
24 | * The `use` keyword brings modules, or the definitions inside modules, into | |
25 | scope so it’s easier to refer to them. | |
cc61c64b | 26 | |
7cac9316 | 27 | We’ll look at each of these parts to see how they fit into the whole. |
cc61c64b XL |
28 | |
29 | ## `mod` and the Filesystem | |
30 | ||
31 | We’ll start our module example by making a new project with Cargo, but instead | |
7cac9316 XL |
32 | of creating a binary crate, we’ll make a library crate: a project that other |
33 | people can pull into their projects as a dependency. For example, the `rand` | |
abe05a73 XL |
34 | crate discussed in Chapter 2 is a library crate that we used as a dependency in |
35 | the guessing game project. | |
7cac9316 | 36 | |
cc61c64b | 37 | We’ll create a skeleton of a library that provides some general networking |
7cac9316 XL |
38 | functionality; we’ll concentrate on the organization of the modules and |
39 | functions but we won’t worry about what code goes in the function bodies. We’ll | |
40 | call our library `communicator`. By default, Cargo will create a library unless | |
41 | another type of project is specified: if we omit the `--bin` option that we’ve | |
42 | been using in all of the chapters preceding this one, our project will be a | |
43 | library: | |
cc61c64b | 44 | |
7cac9316 | 45 | ``` |
cc61c64b XL |
46 | $ cargo new communicator |
47 | $ cd communicator | |
48 | ``` | |
49 | ||
50 | Notice that Cargo generated *src/lib.rs* instead of *src/main.rs*. Inside | |
7cac9316 | 51 | *src/lib.rs* we’ll find the following: |
cc61c64b | 52 | |
7cac9316 | 53 | Filename: src/lib.rs |
cc61c64b | 54 | |
7cac9316 | 55 | ``` |
cc61c64b XL |
56 | #[cfg(test)] |
57 | mod tests { | |
58 | #[test] | |
59 | fn it_works() { | |
abe05a73 | 60 | assert_eq!(2 + 2, 4); |
cc61c64b XL |
61 | } |
62 | } | |
63 | ``` | |
64 | ||
abe05a73 XL |
65 | Cargo creates an example test to help us get our library started, rather than |
66 | the “Hello, world!” binary that we get when we use the `--bin` option. We’ll | |
67 | look at the `#[]` and `mod tests` syntax in the “Using `super` to Access a | |
68 | Parent Module” section later in this chapter, but for now, leave this code at | |
69 | the bottom of *src/lib.rs*. | |
cc61c64b | 70 | |
7cac9316 XL |
71 | Because we don’t have a *src/main.rs* file, there’s nothing for Cargo to |
72 | execute with the `cargo run` command. Therefore, we’ll use the `cargo build` | |
73 | command to compile our library crate’s code. | |
74 | ||
75 | We’ll look at different options for organizing your library’s code that will be | |
76 | suitable in a variety of situations, depending on the intent of the code. | |
cc61c64b XL |
77 | |
78 | ### Module Definitions | |
79 | ||
7cac9316 XL |
80 | For our `communicator` networking library, we’ll first define a module named |
81 | `network` that contains the definition of a function called `connect`. Every | |
82 | module definition in Rust starts with the `mod` keyword. Add this code to the | |
83 | beginning of the *src/lib.rs* file, above the test code: | |
cc61c64b | 84 | |
7cac9316 | 85 | Filename: src/lib.rs |
cc61c64b | 86 | |
7cac9316 | 87 | ``` |
cc61c64b XL |
88 | mod network { |
89 | fn connect() { | |
90 | } | |
91 | } | |
92 | ``` | |
93 | ||
7cac9316 | 94 | After the `mod` keyword, we put the name of the module, `network`, and then a |
abe05a73 | 95 | block of code in curly brackets. Everything inside this block is inside the |
7cac9316 | 96 | namespace `network`. In this case, we have a single function, `connect`. If we |
abe05a73 | 97 | wanted to call this function from code outside the `network` module, we |
7cac9316 XL |
98 | would need to specify the module and use the namespace syntax `::`, like so: |
99 | `network::connect()` rather than just `connect()`. | |
cc61c64b | 100 | |
7cac9316 XL |
101 | We can also have multiple modules, side by side, in the same *src/lib.rs* file. |
102 | For example, to also have a `client` module that has a function named `connect` | |
103 | as well, we can add it as shown in Listing 7-1: | |
cc61c64b | 104 | |
7cac9316 | 105 | Filename: src/lib.rs |
cc61c64b | 106 | |
7cac9316 | 107 | ``` |
cc61c64b XL |
108 | mod network { |
109 | fn connect() { | |
110 | } | |
111 | } | |
112 | ||
113 | mod client { | |
114 | fn connect() { | |
115 | } | |
116 | } | |
117 | ``` | |
118 | ||
7cac9316 | 119 | Listing 7-1: The `network` module and the `client` module defined side by side |
cc61c64b XL |
120 | in *src/lib.rs* |
121 | ||
cc61c64b XL |
122 | Now we have a `network::connect` function and a `client::connect` function. |
123 | These can have completely different functionality, and the function names do | |
7cac9316 XL |
124 | not conflict with each other because they’re in different modules. |
125 | ||
126 | In this case, because we’re building a library, the file that serves as the | |
127 | entry point for building our library is *src/lib.rs*. However, in respect to | |
128 | creating modules, there’s nothing special about *src/lib.rs*. We could also | |
3b2f2976 | 129 | create modules in *src/main.rs* for a binary crate in the same way as we’re |
7cac9316 XL |
130 | creating modules in *src/lib.rs* for the library crate. In fact, we can put |
131 | modules inside of modules, which can be useful as your modules grow to keep | |
132 | related functionality organized together and separate functionality apart. The | |
133 | choice of how you organize your code depends on how you think about the | |
134 | relationship between the parts of your code. For instance, the `client` code | |
135 | and its `connect` function might make more sense to users of our library if | |
136 | they were inside the `network` namespace instead, as in Listing 7-2: | |
137 | ||
138 | Filename: src/lib.rs | |
139 | ||
140 | ``` | |
cc61c64b XL |
141 | mod network { |
142 | fn connect() { | |
143 | } | |
144 | ||
145 | mod client { | |
146 | fn connect() { | |
147 | } | |
148 | } | |
149 | } | |
150 | ``` | |
151 | ||
7cac9316 | 152 | Listing 7-2: Moving the `client` module inside the `network` module |
cc61c64b XL |
153 | |
154 | In your *src/lib.rs* file, replace the existing `mod network` and `mod client` | |
7cac9316 XL |
155 | definitions with the ones in Listing 7-2, which have the `client` module as an |
156 | inner module of `network`. Now we have the functions `network::connect` and | |
cc61c64b | 157 | `network::client::connect`: again, the two functions named `connect` don’t |
7cac9316 | 158 | conflict with each other because they’re in different namespaces. |
cc61c64b XL |
159 | |
160 | In this way, modules form a hierarchy. The contents of *src/lib.rs* are at the | |
161 | topmost level, and the submodules are at lower levels. Here’s what the | |
7cac9316 XL |
162 | organization of our example in Listing 7-1 looks like when thought of as a |
163 | hierarchy: | |
cc61c64b | 164 | |
7cac9316 | 165 | ``` |
cc61c64b XL |
166 | communicator |
167 | ├── network | |
168 | └── client | |
169 | ``` | |
170 | ||
7cac9316 | 171 | And here’s the hierarchy corresponding to the example in Listing 7-2: |
cc61c64b | 172 | |
7cac9316 | 173 | ``` |
cc61c64b XL |
174 | communicator |
175 | └── network | |
176 | └── client | |
177 | ``` | |
178 | ||
7cac9316 XL |
179 | The hierarchy shows that in Listing 7-2, `client` is a child of the `network` |
180 | module rather than a sibling. More complicated projects can have many modules, | |
181 | and they’ll need to be organized logically in order to keep track of them. What | |
182 | “logically” means in your project is up to you and depends on how you and your | |
183 | library’s users think about your project’s domain. Use the techniques shown | |
184 | here to create side-by-side modules and nested modules in whatever structure | |
185 | you would like. | |
cc61c64b XL |
186 | |
187 | ### Moving Modules to Other Files | |
188 | ||
189 | Modules form a hierarchical structure, much like another structure in computing | |
7cac9316 XL |
190 | that you’re used to: filesystems! We can use Rust’s module system along with |
191 | multiple files to split up Rust projects so not everything lives in | |
192 | *src/lib.rs* or *src/main.rs*. For this example, let’s start with the code in | |
193 | Listing 7-3: | |
cc61c64b | 194 | |
7cac9316 | 195 | Filename: src/lib.rs |
cc61c64b | 196 | |
7cac9316 | 197 | ``` |
cc61c64b XL |
198 | mod client { |
199 | fn connect() { | |
200 | } | |
201 | } | |
202 | ||
203 | mod network { | |
204 | fn connect() { | |
205 | } | |
206 | ||
207 | mod server { | |
208 | fn connect() { | |
209 | } | |
210 | } | |
211 | } | |
212 | ``` | |
213 | ||
cc61c64b XL |
214 | Listing 7-3: Three modules, `client`, `network`, and `network::server`, all |
215 | defined in *src/lib.rs* | |
216 | ||
7cac9316 | 217 | The file *src/lib.rs* has this module hierarchy: |
cc61c64b | 218 | |
7cac9316 | 219 | ``` |
cc61c64b XL |
220 | communicator |
221 | ├── client | |
222 | └── network | |
223 | └── server | |
224 | ``` | |
225 | ||
7cac9316 XL |
226 | If these modules had many functions, and those functions were becoming lengthy, |
227 | it would be difficult to scroll through this file to find the code we wanted to | |
abe05a73 XL |
228 | work with. Because the functions are nested inside one or more `mod` blocks, |
229 | the lines of code inside the functions will start getting lengthy as well. | |
230 | These would be good reasons to separate the `client`, `network`, and `server` | |
231 | modules from *src/lib.rs* and place them into their own files. | |
cc61c64b | 232 | |
abe05a73 XL |
233 | First, replace the `client` module code with only the declaration of the |
234 | `client` module, so that your *src/lib.rs* looks like the following: | |
cc61c64b | 235 | |
7cac9316 | 236 | Filename: src/lib.rs |
cc61c64b | 237 | |
7cac9316 | 238 | ``` |
cc61c64b XL |
239 | mod client; |
240 | ||
241 | mod network { | |
242 | fn connect() { | |
243 | } | |
244 | ||
245 | mod server { | |
246 | fn connect() { | |
247 | } | |
248 | } | |
249 | } | |
250 | ``` | |
251 | ||
7cac9316 XL |
252 | We’re still *declaring* the `client` module here, but by replacing the block |
253 | with a semicolon, we’re telling Rust to look in another location for the code | |
254 | defined within the scope of the `client` module. In other words, the line `mod | |
255 | client;` means: | |
256 | ||
257 | ``` | |
258 | mod client { | |
259 | // contents of client.rs | |
260 | } | |
261 | ``` | |
cc61c64b | 262 | |
7cac9316 XL |
263 | Now we need to create the external file with that module name. Create a |
264 | *client.rs* file in your *src/* directory and open it. Then enter the | |
cc61c64b XL |
265 | following, which is the `connect` function in the `client` module that we |
266 | removed in the previous step: | |
267 | ||
7cac9316 | 268 | Filename: src/client.rs |
cc61c64b | 269 | |
7cac9316 | 270 | ``` |
cc61c64b XL |
271 | fn connect() { |
272 | } | |
273 | ``` | |
274 | ||
7cac9316 XL |
275 | Note that we don’t need a `mod` declaration in this file because we already |
276 | declared the `client` module with `mod` in *src/lib.rs*. This file just | |
cc61c64b XL |
277 | provides the *contents* of the `client` module. If we put a `mod client` here, |
278 | we’d be giving the `client` module its own submodule named `client`! | |
279 | ||
280 | Rust only knows to look in *src/lib.rs* by default. If we want to add more | |
281 | files to our project, we need to tell Rust in *src/lib.rs* to look in other | |
282 | files; this is why `mod client` needs to be defined in *src/lib.rs* and can’t | |
283 | be defined in *src/client.rs*. | |
284 | ||
7cac9316 XL |
285 | Now the project should compile successfully, although you’ll get a few |
286 | warnings. Remember to use `cargo build` instead of `cargo run` because we have | |
287 | a library crate rather than a binary crate: | |
cc61c64b | 288 | |
7cac9316 | 289 | ``` |
cc61c64b XL |
290 | $ cargo build |
291 | Compiling communicator v0.1.0 (file:///projects/communicator) | |
abe05a73 | 292 | warning: function is never used: `connect` |
cc61c64b XL |
293 | --> src/client.rs:1:1 |
294 | | | |
abe05a73 XL |
295 | 1 | / fn connect() { |
296 | 2 | | } | |
297 | | |_^ | |
298 | | | |
299 | = note: #[warn(dead_code)] on by default | |
cc61c64b | 300 | |
abe05a73 | 301 | warning: function is never used: `connect` |
cc61c64b XL |
302 | --> src/lib.rs:4:5 |
303 | | | |
abe05a73 XL |
304 | 4 | / fn connect() { |
305 | 5 | | } | |
306 | | |_____^ | |
cc61c64b | 307 | |
abe05a73 | 308 | warning: function is never used: `connect` |
cc61c64b XL |
309 | --> src/lib.rs:8:9 |
310 | | | |
abe05a73 XL |
311 | 8 | / fn connect() { |
312 | 9 | | } | |
313 | | |_________^ | |
cc61c64b XL |
314 | ``` |
315 | ||
316 | These warnings tell us that we have functions that are never used. Don’t worry | |
abe05a73 XL |
317 | about these warnings for now; we’ll address them later in this chapter in the |
318 | “Controlling Visibility with `pub`” section. The good news is that they’re just | |
7cac9316 XL |
319 | warnings; our project built successfully! |
320 | ||
7cac9316 | 321 | Next, let’s extract the `network` module into its own file using the same |
cc61c64b XL |
322 | pattern. In *src/lib.rs*, delete the body of the `network` module and add a |
323 | semicolon to the declaration, like so: | |
324 | ||
7cac9316 | 325 | Filename: src/lib.rs |
cc61c64b | 326 | |
7cac9316 | 327 | ``` |
cc61c64b XL |
328 | mod client; |
329 | ||
330 | mod network; | |
331 | ``` | |
332 | ||
333 | Then create a new *src/network.rs* file and enter the following: | |
334 | ||
7cac9316 | 335 | Filename: src/network.rs |
cc61c64b | 336 | |
7cac9316 | 337 | ``` |
cc61c64b XL |
338 | fn connect() { |
339 | } | |
340 | ||
341 | mod server { | |
342 | fn connect() { | |
343 | } | |
344 | } | |
345 | ``` | |
346 | ||
347 | Notice that we still have a `mod` declaration within this module file; this is | |
7cac9316 | 348 | because we still want `server` to be a submodule of `network`. |
cc61c64b | 349 | |
7cac9316 XL |
350 | Run `cargo build` again. Success! We have one more module to extract: `server`. |
351 | Because it’s a submodule—that is, a module within a module—our current tactic | |
352 | of extracting a module into a file named after that module won’t work. We’ll | |
353 | try anyway so you can see the error. First, change *src/network.rs* to have | |
354 | `mod server;` instead of the `server` module’s contents: | |
cc61c64b | 355 | |
7cac9316 | 356 | Filename: src/network.rs |
cc61c64b | 357 | |
7cac9316 | 358 | ``` |
cc61c64b XL |
359 | fn connect() { |
360 | } | |
361 | ||
362 | mod server; | |
363 | ``` | |
364 | ||
365 | Then create a *src/server.rs* file and enter the contents of the `server` | |
366 | module that we extracted: | |
367 | ||
7cac9316 | 368 | Filename: src/server.rs |
cc61c64b | 369 | |
7cac9316 | 370 | ``` |
cc61c64b XL |
371 | fn connect() { |
372 | } | |
373 | ``` | |
374 | ||
375 | When we try to `cargo build`, we’ll get the error shown in Listing 7-4: | |
376 | ||
7cac9316 | 377 | ``` |
cc61c64b XL |
378 | $ cargo build |
379 | Compiling communicator v0.1.0 (file:///projects/communicator) | |
380 | error: cannot declare a new module at this location | |
381 | --> src/network.rs:4:5 | |
382 | | | |
383 | 4 | mod server; | |
384 | | ^^^^^^ | |
385 | | | |
abe05a73 | 386 | note: maybe move this module `src/network.rs` to its own directory via `src/network/mod.rs` |
cc61c64b XL |
387 | --> src/network.rs:4:5 |
388 | | | |
389 | 4 | mod server; | |
390 | | ^^^^^^ | |
391 | note: ... or maybe `use` the module `server` instead of possibly redeclaring it | |
392 | --> src/network.rs:4:5 | |
393 | | | |
394 | 4 | mod server; | |
395 | | ^^^^^^ | |
396 | ``` | |
397 | ||
cc61c64b XL |
398 | Listing 7-4: Error when trying to extract the `server` submodule into |
399 | *src/server.rs* | |
400 | ||
cc61c64b XL |
401 | The error says we `cannot declare a new module at this location` and is |
402 | pointing to the `mod server;` line in *src/network.rs*. So *src/network.rs* is | |
7cac9316 | 403 | different than *src/lib.rs* somehow: keep reading to understand why. |
cc61c64b | 404 | |
7cac9316 XL |
405 | The note in the middle of Listing 7-4 is actually very helpful because it |
406 | points out something we haven’t yet talked about doing: | |
cc61c64b | 407 | |
7cac9316 XL |
408 | ``` |
409 | note: maybe move this module `network` to its own directory via | |
410 | `network/mod.rs` | |
cc61c64b XL |
411 | ``` |
412 | ||
413 | Instead of continuing to follow the same file naming pattern we used | |
414 | previously, we can do what the note suggests: | |
415 | ||
7cac9316 XL |
416 | 1. Make a new *directory* named *network*, the parent module’s name. |
417 | 2. Move the *src/network.rs* file into the new *network* directory, and | |
abe05a73 | 418 | rename it to *src/network/mod.rs*. |
7cac9316 | 419 | 3. Move the submodule file *src/server.rs* into the *network* directory. |
cc61c64b XL |
420 | |
421 | Here are commands to carry out these steps: | |
422 | ||
7cac9316 | 423 | ``` |
cc61c64b XL |
424 | $ mkdir src/network |
425 | $ mv src/network.rs src/network/mod.rs | |
426 | $ mv src/server.rs src/network | |
427 | ``` | |
428 | ||
7cac9316 | 429 | Now when we try to run `cargo build`, compilation will work (we’ll still have |
cc61c64b XL |
430 | warnings though). Our module layout still looks like this, which is exactly the |
431 | same as it did when we had all the code in *src/lib.rs* in Listing 7-3: | |
432 | ||
7cac9316 | 433 | ``` |
cc61c64b XL |
434 | communicator |
435 | ├── client | |
436 | └── network | |
437 | └── server | |
438 | ``` | |
439 | ||
440 | The corresponding file layout now looks like this: | |
441 | ||
7cac9316 | 442 | ``` |
cc61c64b | 443 | ├── src |
7cac9316 XL |
444 | │ ├── client.rs |
445 | │ ├── lib.rs | |
446 | │ └── network | |
447 | │ ├── mod.rs | |
448 | │ └── server.rs | |
cc61c64b XL |
449 | ``` |
450 | ||
451 | So when we wanted to extract the `network::server` module, why did we have to | |
7cac9316 XL |
452 | also change the *src/network.rs* file to the *src/network/mod.rs* file and put |
453 | the code for `network::server` in the *network* directory in | |
454 | *src/network/server.rs* instead of just being able to extract the | |
cc61c64b | 455 | `network::server` module into *src/server.rs*? The reason is that Rust wouldn’t |
7cac9316 XL |
456 | be able to recognize that `server` was supposed to be a submodule of `network` |
457 | if the *server.rs* file was in the *src* directory. To clarify Rust’s behavior | |
458 | here, let’s consider a different example with the following module hierarchy, | |
459 | where all the definitions are in *src/lib.rs*: | |
cc61c64b | 460 | |
7cac9316 | 461 | ``` |
cc61c64b XL |
462 | communicator |
463 | ├── client | |
464 | └── network | |
465 | └── client | |
466 | ``` | |
467 | ||
7cac9316 XL |
468 | In this example, we have three modules again: `client`, `network`, and |
469 | `network::client`. Following the same steps we did earlier for extracting | |
470 | modules into files, we would create *src/client.rs* for the `client` module. | |
471 | For the `network` module, we would create *src/network.rs*. But we wouldn’t be | |
472 | able to extract the `network::client` module into a *src/client.rs* file | |
473 | because that already exists for the top-level `client` module! If we could put | |
474 | the code for *both* the `client` and `network::client` modules in the | |
475 | *src/client.rs* file, Rust wouldn’t have any way to know whether the code was | |
476 | for `client` or for `network::client`. | |
477 | ||
478 | Therefore, in order to extract a file for the `network::client` submodule of | |
479 | the `network` module, we needed to create a directory for the `network` module | |
480 | instead of a *src/network.rs* file. The code that is in the `network` module | |
481 | then goes into the *src/network/mod.rs* file, and the submodule | |
cc61c64b XL |
482 | `network::client` can have its own *src/network/client.rs* file. Now the |
483 | top-level *src/client.rs* is unambiguously the code that belongs to the | |
484 | `client` module. | |
485 | ||
7cac9316 | 486 | ### Rules of Module Filesystems |
cc61c64b | 487 | |
7cac9316 | 488 | Let’s summarize the rules of modules with regard to files: |
cc61c64b XL |
489 | |
490 | * If a module named `foo` has no submodules, you should put the declarations | |
491 | for `foo` in a file named *foo.rs*. | |
492 | * If a module named `foo` does have submodules, you should put the declarations | |
493 | for `foo` in a file named *foo/mod.rs*. | |
494 | ||
7cac9316 XL |
495 | These rules apply recursively, so if a module named `foo` has a submodule named |
496 | `bar` and `bar` does not have submodules, you should have the following files | |
497 | in your *src* directory: | |
cc61c64b | 498 | |
7cac9316 | 499 | ``` |
cc61c64b | 500 | ├── foo |
7cac9316 XL |
501 | │ ├── bar.rs (contains the declarations in `foo::bar`) |
502 | │ └── mod.rs (contains the declarations in `foo`, including `mod bar`) | |
cc61c64b XL |
503 | ``` |
504 | ||
7cac9316 XL |
505 | The modules should be declared in their parent module’s file using the `mod` |
506 | keyword. | |
cc61c64b | 507 | |
7cac9316 | 508 | Next, we’ll talk about the `pub` keyword and get rid of those warnings! |
cc61c64b XL |
509 | |
510 | ## Controlling Visibility with `pub` | |
511 | ||
512 | We resolved the error messages shown in Listing 7-4 by moving the `network` and | |
513 | `network::server` code into the *src/network/mod.rs* and | |
514 | *src/network/server.rs* files, respectively. At that point, `cargo build` was | |
7cac9316 | 515 | able to build our project, but we still get warning messages about the |
cc61c64b XL |
516 | `client::connect`, `network::connect`, and `network::server::connect` functions |
517 | not being used: | |
518 | ||
7cac9316 | 519 | ``` |
abe05a73 XL |
520 | warning: function is never used: `connect` |
521 | --> src/client.rs:1:1 | |
522 | | | |
523 | 1 | / fn connect() { | |
524 | 2 | | } | |
525 | | |_^ | |
cc61c64b | 526 | | |
abe05a73 | 527 | = note: #[warn(dead_code)] on by default |
cc61c64b | 528 | |
abe05a73 | 529 | warning: function is never used: `connect` |
cc61c64b XL |
530 | --> src/network/mod.rs:1:1 |
531 | | | |
abe05a73 XL |
532 | 1 | / fn connect() { |
533 | 2 | | } | |
534 | | |_^ | |
cc61c64b | 535 | |
abe05a73 | 536 | warning: function is never used: `connect` |
cc61c64b XL |
537 | --> src/network/server.rs:1:1 |
538 | | | |
abe05a73 XL |
539 | 1 | / fn connect() { |
540 | 2 | | } | |
541 | | |_^ | |
cc61c64b XL |
542 | ``` |
543 | ||
544 | So why are we receiving these warnings? After all, we’re building a library | |
7cac9316 XL |
545 | with functions that are intended to be used by our *users*, not necessarily by |
546 | us within our own project, so it shouldn’t matter that these `connect` | |
cc61c64b | 547 | functions go unused. The point of creating them is that they will be used by |
7cac9316 | 548 | another project, not our own. |
cc61c64b XL |
549 | |
550 | To understand why this program invokes these warnings, let’s try using the | |
7cac9316 XL |
551 | `connect` library from another project, calling it externally. To do that, |
552 | we’ll create a binary crate in the same directory as our library crate by | |
553 | making a *src/main.rs* file containing this code: | |
cc61c64b | 554 | |
7cac9316 | 555 | Filename: src/main.rs |
cc61c64b | 556 | |
7cac9316 | 557 | ``` |
cc61c64b XL |
558 | extern crate communicator; |
559 | ||
560 | fn main() { | |
561 | communicator::client::connect(); | |
562 | } | |
563 | ``` | |
564 | ||
565 | We use the `extern crate` command to bring the `communicator` library crate | |
7cac9316 XL |
566 | into scope. Our package now contains *two* crates. Cargo treats *src/main.rs* |
567 | as the root file of a binary crate, which is separate from the existing library | |
568 | crate whose root file is *src/lib.rs*. This pattern is quite common for | |
569 | executable projects: most functionality is in a library crate, and the binary | |
570 | crate uses that library crate. As a result, other programs can also use the | |
571 | library crate, and it’s a nice separation of concerns. | |
572 | ||
573 | From the point of view of a crate outside the `communicator` library looking | |
574 | in, all the modules we’ve been creating are within a module that has the same | |
575 | name as the crate, `communicator`. We call the top-level module of a crate the | |
576 | *root module*. | |
577 | ||
578 | Also note that even if we’re using an external crate within a submodule of our | |
cc61c64b XL |
579 | project, the `extern crate` should go in our root module (so in *src/main.rs* |
580 | or *src/lib.rs*). Then, in our submodules, we can refer to items from external | |
581 | crates as if the items are top-level modules. | |
582 | ||
7cac9316 XL |
583 | Right now, our binary crate just calls our library’s `connect` function from |
584 | the `client` module. However, invoking `cargo build` will now give us an error | |
cc61c64b XL |
585 | after the warnings: |
586 | ||
7cac9316 | 587 | ``` |
abe05a73 | 588 | error[E0603]: module `client` is private |
cc61c64b XL |
589 | --> src/main.rs:4:5 |
590 | | | |
591 | 4 | communicator::client::connect(); | |
592 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
593 | ``` | |
594 | ||
7cac9316 XL |
595 | Ah ha! This error tells us that the `client` module is private, which is the |
596 | crux of the warnings. It’s also the first time we’ve run into the concepts of | |
cc61c64b XL |
597 | *public* and *private* in the context of Rust. The default state of all code in |
598 | Rust is private: no one else is allowed to use the code. If you don’t use a | |
7cac9316 XL |
599 | private function within your program, because your program is the only code |
600 | allowed to use that function, Rust will warn you that the function has gone | |
601 | unused. | |
602 | ||
603 | After we specify that a function like `client::connect` is public, not only | |
604 | will our call to that function from our binary crate be allowed, but the | |
605 | warning that the function is unused will go away. Marking a function as public | |
606 | lets Rust know that the function will be used by code outside of our program. | |
607 | Rust considers the theoretical external usage that’s now possible as the | |
abe05a73 XL |
608 | function “being used.” Thus, when a function is marked public, Rust will not |
609 | require that it be used in our program and will stop warning that the function | |
610 | is unused. | |
cc61c64b XL |
611 | |
612 | ### Making a Function Public | |
613 | ||
abe05a73 XL |
614 | To tell Rust to make a function public, we add the `pub` keyword to the start |
615 | of the declaration. We’ll focus on fixing the warning that indicates | |
616 | `client::connect` has gone unused for now, as well as the `` module `client` is | |
617 | private `` error from our binary crate. Modify *src/lib.rs* to make the | |
618 | `client` module public, like so: | |
cc61c64b | 619 | |
7cac9316 | 620 | Filename: src/lib.rs |
cc61c64b | 621 | |
7cac9316 | 622 | ``` |
cc61c64b XL |
623 | pub mod client; |
624 | ||
625 | mod network; | |
626 | ``` | |
627 | ||
7cac9316 | 628 | The `pub` keyword is placed right before `mod`. Let’s try building again: |
cc61c64b | 629 | |
7cac9316 | 630 | ``` |
abe05a73 | 631 | error[E0603]: function `connect` is private |
cc61c64b XL |
632 | --> src/main.rs:4:5 |
633 | | | |
634 | 4 | communicator::client::connect(); | |
635 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
636 | ``` | |
637 | ||
638 | Hooray! We have a different error! Yes, different error messages are a cause | |
3b2f2976 XL |
639 | for celebration. The new error shows `` function `connect` is private ``, so |
640 | let’s edit *src/client.rs* to make `client::connect` public too: | |
cc61c64b | 641 | |
7cac9316 | 642 | Filename: src/client.rs |
cc61c64b | 643 | |
7cac9316 | 644 | ``` |
cc61c64b XL |
645 | pub fn connect() { |
646 | } | |
647 | ``` | |
648 | ||
7cac9316 | 649 | Now run `cargo build` again: |
cc61c64b | 650 | |
7cac9316 | 651 | ``` |
abe05a73 | 652 | warning: function is never used: `connect` |
cc61c64b XL |
653 | --> src/network/mod.rs:1:1 |
654 | | | |
abe05a73 XL |
655 | 1 | / fn connect() { |
656 | 2 | | } | |
657 | | |_^ | |
658 | | | |
659 | = note: #[warn(dead_code)] on by default | |
cc61c64b | 660 | |
abe05a73 | 661 | warning: function is never used: `connect` |
cc61c64b XL |
662 | --> src/network/server.rs:1:1 |
663 | | | |
abe05a73 XL |
664 | 1 | / fn connect() { |
665 | 2 | | } | |
666 | | |_^ | |
cc61c64b XL |
667 | ``` |
668 | ||
7cac9316 XL |
669 | The code compiled, and the warning about `client::connect` not being used is |
670 | gone! | |
cc61c64b | 671 | |
7cac9316 XL |
672 | Unused code warnings don’t always indicate that an item in your code needs to |
673 | be made public: if you *didn’t* want these functions to be part of your public | |
674 | API, unused code warnings could be alerting you to code you no longer need that | |
675 | you can safely delete. They could also be alerting you to a bug if you had just | |
cc61c64b XL |
676 | accidentally removed all places within your library where this function is |
677 | called. | |
678 | ||
7cac9316 XL |
679 | But in this case, we *do* want the other two functions to be part of our |
680 | crate’s public API, so let’s mark them as `pub` as well to get rid of the | |
681 | remaining warnings. Modify *src/network/mod.rs* to look like the following: | |
cc61c64b | 682 | |
7cac9316 | 683 | Filename: src/network/mod.rs |
cc61c64b | 684 | |
7cac9316 | 685 | ``` |
cc61c64b XL |
686 | pub fn connect() { |
687 | } | |
688 | ||
689 | mod server; | |
690 | ``` | |
691 | ||
7cac9316 | 692 | Then compile the code: |
cc61c64b | 693 | |
7cac9316 | 694 | ``` |
abe05a73 | 695 | warning: function is never used: `connect` |
cc61c64b XL |
696 | --> src/network/mod.rs:1:1 |
697 | | | |
abe05a73 XL |
698 | 1 | / pub fn connect() { |
699 | 2 | | } | |
700 | | |_^ | |
701 | | | |
702 | = note: #[warn(dead_code)] on by default | |
cc61c64b | 703 | |
abe05a73 | 704 | warning: function is never used: `connect` |
cc61c64b XL |
705 | --> src/network/server.rs:1:1 |
706 | | | |
abe05a73 XL |
707 | 1 | / fn connect() { |
708 | 2 | | } | |
709 | | |_^ | |
cc61c64b XL |
710 | ``` |
711 | ||
7cac9316 XL |
712 | Hmmm, we’re still getting an unused function warning, even though |
713 | `network::connect` is set to `pub`. The reason is that the function is public | |
cc61c64b | 714 | within the module, but the `network` module that the function resides in is not |
7cac9316 | 715 | public. We’re working from the interior of the library out this time, whereas |
cc61c64b | 716 | with `client::connect` we worked from the outside in. We need to change |
7cac9316 | 717 | *src/lib.rs* to make `network` public too, like so: |
cc61c64b | 718 | |
7cac9316 | 719 | Filename: src/lib.rs |
cc61c64b | 720 | |
7cac9316 | 721 | ``` |
cc61c64b XL |
722 | pub mod client; |
723 | ||
724 | pub mod network; | |
725 | ``` | |
726 | ||
7cac9316 | 727 | Now when we compile, that warning is gone: |
cc61c64b | 728 | |
7cac9316 | 729 | ``` |
abe05a73 | 730 | warning: function is never used: `connect` |
cc61c64b XL |
731 | --> src/network/server.rs:1:1 |
732 | | | |
abe05a73 XL |
733 | 1 | / fn connect() { |
734 | 2 | | } | |
735 | | |_^ | |
736 | | | |
737 | = note: #[warn(dead_code)] on by default | |
cc61c64b XL |
738 | ``` |
739 | ||
7cac9316 | 740 | Only one warning is left! Try to fix this one on your own! |
cc61c64b XL |
741 | |
742 | ### Privacy Rules | |
743 | ||
744 | Overall, these are the rules for item visibility: | |
745 | ||
746 | 1. If an item is public, it can be accessed through any of its parent modules. | |
3b2f2976 XL |
747 | 2. If an item is private, it can be accessed only by its immediate parent |
748 | module and any of the parent’s child modules. | |
cc61c64b XL |
749 | |
750 | ### Privacy Examples | |
751 | ||
7cac9316 XL |
752 | Let’s look at a few more privacy examples to get some practice. Create a new |
753 | library project and enter the code in Listing 7-5 into your new project’s | |
754 | *src/lib.rs*: | |
cc61c64b | 755 | |
7cac9316 | 756 | Filename: src/lib.rs |
cc61c64b | 757 | |
7cac9316 | 758 | ``` |
cc61c64b XL |
759 | mod outermost { |
760 | pub fn middle_function() {} | |
761 | ||
762 | fn middle_secret_function() {} | |
763 | ||
764 | mod inside { | |
765 | pub fn inner_function() {} | |
766 | ||
767 | fn secret_function() {} | |
768 | } | |
769 | } | |
770 | ||
771 | fn try_me() { | |
772 | outermost::middle_function(); | |
773 | outermost::middle_secret_function(); | |
774 | outermost::inside::inner_function(); | |
775 | outermost::inside::secret_function(); | |
776 | } | |
777 | ``` | |
778 | ||
cc61c64b XL |
779 | Listing 7-5: Examples of private and public functions, some of which are |
780 | incorrect | |
781 | ||
7cac9316 XL |
782 | Before you try to compile this code, make a guess about which lines in the |
783 | `try_me` function will have errors. Then, try compiling the code to see whether | |
784 | you were right, and read on for the discussion of the errors! | |
cc61c64b XL |
785 | |
786 | #### Looking at the Errors | |
787 | ||
788 | The `try_me` function is in the root module of our project. The module named | |
7cac9316 XL |
789 | `outermost` is private, but the second privacy rule states that the `try_me` |
790 | function is allowed to access the `outermost` module because `outermost` is in | |
791 | the current (root) module, as is `try_me`. | |
cc61c64b | 792 | |
7cac9316 XL |
793 | The call to `outermost::middle_function` will work because `middle_function` is |
794 | public, and `try_me` is accessing `middle_function` through its parent module | |
795 | `outermost`. We determined in the previous paragraph that this module is | |
796 | accessible. | |
cc61c64b XL |
797 | |
798 | The call to `outermost::middle_secret_function` will cause a compilation error. | |
799 | `middle_secret_function` is private, so the second rule applies. The root | |
800 | module is neither the current module of `middle_secret_function` (`outermost` | |
801 | is), nor is it a child module of the current module of `middle_secret_function`. | |
802 | ||
803 | The module named `inside` is private and has no child modules, so it can only | |
7cac9316 XL |
804 | be accessed by its current module `outermost`. That means the `try_me` function |
805 | is not allowed to call `outermost::inside::inner_function` or | |
806 | `outermost::inside::secret_function`. | |
cc61c64b XL |
807 | |
808 | #### Fixing the Errors | |
809 | ||
810 | Here are some suggestions for changing the code in an attempt to fix the | |
811 | errors. Before you try each one, make a guess as to whether it will fix the | |
7cac9316 XL |
812 | errors, and then compile the code to see whether or not you’re right, using the |
813 | privacy rules to understand why. | |
cc61c64b XL |
814 | |
815 | * What if the `inside` module was public? | |
816 | * What if `outermost` was public and `inside` was private? | |
817 | * What if, in the body of `inner_function`, you called | |
818 | `::outermost::middle_secret_function()`? (The two colons at the beginning mean | |
819 | that we want to refer to the modules starting from the root module.) | |
820 | ||
821 | Feel free to design more experiments and try them out! | |
822 | ||
7cac9316 | 823 | Next, let’s talk about bringing items into scope with the `use` keyword. |
cc61c64b | 824 | |
abe05a73 | 825 | ## Referring to Names in Different Modules |
cc61c64b XL |
826 | |
827 | We’ve covered how to call functions defined within a module using the module | |
828 | name as part of the call, as in the call to the `nested_modules` function shown | |
7cac9316 | 829 | here in Listing 7-6: |
cc61c64b | 830 | |
7cac9316 | 831 | Filename: src/main.rs |
cc61c64b | 832 | |
7cac9316 | 833 | ``` |
cc61c64b XL |
834 | pub mod a { |
835 | pub mod series { | |
836 | pub mod of { | |
837 | pub fn nested_modules() {} | |
838 | } | |
839 | } | |
840 | } | |
841 | ||
842 | fn main() { | |
843 | a::series::of::nested_modules(); | |
844 | } | |
845 | ``` | |
846 | ||
7cac9316 | 847 | Listing 7-6: Calling a function by fully specifying its enclosing module’s path |
cc61c64b XL |
848 | |
849 | As you can see, referring to the fully qualified name can get quite lengthy. | |
7cac9316 | 850 | Fortunately, Rust has a keyword to make these calls more concise. |
cc61c64b | 851 | |
abe05a73 | 852 | ### Bringing Names into Scope with the `use` Keyword |
cc61c64b | 853 | |
7cac9316 XL |
854 | Rust’s `use` keyword shortens lengthy function calls by bringing the modules of |
855 | the function you want to call into scope. Here’s an example of bringing the | |
856 | `a::series::of` module into a binary crate’s root scope: | |
cc61c64b | 857 | |
7cac9316 | 858 | Filename: src/main.rs |
cc61c64b | 859 | |
7cac9316 | 860 | ``` |
cc61c64b XL |
861 | pub mod a { |
862 | pub mod series { | |
863 | pub mod of { | |
864 | pub fn nested_modules() {} | |
865 | } | |
866 | } | |
867 | } | |
868 | ||
869 | use a::series::of; | |
870 | ||
871 | fn main() { | |
872 | of::nested_modules(); | |
873 | } | |
874 | ``` | |
875 | ||
876 | The line `use a::series::of;` means that rather than using the full | |
877 | `a::series::of` path wherever we want to refer to the `of` module, we can use | |
878 | `of`. | |
879 | ||
7cac9316 XL |
880 | The `use` keyword brings only what we’ve specified into scope: it does not |
881 | bring children of modules into scope. That’s why we still have to use | |
cc61c64b XL |
882 | `of::nested_modules` when we want to call the `nested_modules` function. |
883 | ||
7cac9316 XL |
884 | We could have chosen to bring the function into scope by instead specifying the |
885 | function in the `use` as follows: | |
cc61c64b | 886 | |
7cac9316 | 887 | ``` |
cc61c64b XL |
888 | pub mod a { |
889 | pub mod series { | |
890 | pub mod of { | |
891 | pub fn nested_modules() {} | |
892 | } | |
893 | } | |
894 | } | |
895 | ||
896 | use a::series::of::nested_modules; | |
897 | ||
898 | fn main() { | |
899 | nested_modules(); | |
900 | } | |
901 | ``` | |
902 | ||
7cac9316 | 903 | Doing so allows us to exclude all the modules and reference the function |
cc61c64b XL |
904 | directly. |
905 | ||
abe05a73 XL |
906 | Because enums also form a sort of namespace like modules, we can bring an |
907 | enum’s variants into scope with `use` as well. For any kind of `use` statement, | |
908 | if you’re bringing multiple items from one namespace into scope, you can list | |
909 | them using curly brackets and commas in the last position, like so: | |
cc61c64b | 910 | |
7cac9316 | 911 | ``` |
cc61c64b XL |
912 | enum TrafficLight { |
913 | Red, | |
914 | Yellow, | |
915 | Green, | |
916 | } | |
917 | ||
918 | use TrafficLight::{Red, Yellow}; | |
919 | ||
920 | fn main() { | |
921 | let red = Red; | |
922 | let yellow = Yellow; | |
7cac9316 | 923 | let green = TrafficLight::Green; |
cc61c64b XL |
924 | } |
925 | ``` | |
926 | ||
3b2f2976 XL |
927 | We’re still specifying the `TrafficLight` namespace for the `Green` variant |
928 | because we didn’t include `Green` in the `use` statement. | |
7cac9316 | 929 | |
abe05a73 | 930 | ### Bringing All Names into Scope with a Glob |
cc61c64b | 931 | |
abe05a73 XL |
932 | To bring all the items in a namespace into scope at once, we can use the `*` |
933 | syntax, which is called the *glob operator*. This example brings all the | |
934 | variants of an enum into scope without having to list each specifically: | |
cc61c64b | 935 | |
7cac9316 | 936 | ``` |
cc61c64b XL |
937 | enum TrafficLight { |
938 | Red, | |
939 | Yellow, | |
940 | Green, | |
941 | } | |
942 | ||
943 | use TrafficLight::*; | |
944 | ||
945 | fn main() { | |
946 | let red = Red; | |
947 | let yellow = Yellow; | |
948 | let green = Green; | |
949 | } | |
950 | ``` | |
951 | ||
abe05a73 | 952 | The `*` will bring into scope all the visible items in the `TrafficLight` |
7cac9316 XL |
953 | namespace. You should use globs sparingly: they are convenient, but this might |
954 | also pull in more items than you expected and cause naming conflicts. | |
cc61c64b XL |
955 | |
956 | ### Using `super` to Access a Parent Module | |
957 | ||
7cac9316 XL |
958 | As we saw at the beginning of this chapter, when you create a library crate, |
959 | Cargo makes a `tests` module for you. Let’s go into more detail about that now. | |
960 | In your `communicator` project, open *src/lib.rs*: | |
cc61c64b | 961 | |
7cac9316 | 962 | Filename: src/lib.rs |
cc61c64b | 963 | |
7cac9316 | 964 | ``` |
cc61c64b XL |
965 | pub mod client; |
966 | ||
967 | pub mod network; | |
968 | ||
969 | #[cfg(test)] | |
970 | mod tests { | |
971 | #[test] | |
972 | fn it_works() { | |
abe05a73 | 973 | assert_eq!(2 + 2, 4); |
cc61c64b XL |
974 | } |
975 | } | |
976 | ``` | |
977 | ||
7cac9316 | 978 | Chapter 11 explains more about testing, but parts of this example should make |
cc61c64b XL |
979 | sense now: we have a module named `tests` that lives next to our other modules |
980 | and contains one function named `it_works`. Even though there are special | |
981 | annotations, the `tests` module is just another module! So our module hierarchy | |
982 | looks like this: | |
983 | ||
7cac9316 | 984 | ``` |
cc61c64b XL |
985 | communicator |
986 | ├── client | |
987 | ├── network | |
988 | | └── client | |
989 | └── tests | |
990 | ``` | |
991 | ||
992 | Tests are for exercising the code within our library, so let’s try to call our | |
7cac9316 | 993 | `client::connect` function from this `it_works` function, even though we won’t |
abe05a73 | 994 | be checking any functionality right now. This won't work yet: |
cc61c64b | 995 | |
7cac9316 | 996 | Filename: src/lib.rs |
cc61c64b | 997 | |
7cac9316 | 998 | ``` |
cc61c64b XL |
999 | #[cfg(test)] |
1000 | mod tests { | |
1001 | #[test] | |
1002 | fn it_works() { | |
1003 | client::connect(); | |
1004 | } | |
1005 | } | |
1006 | ``` | |
1007 | ||
1008 | Run the tests by invoking the `cargo test` command: | |
1009 | ||
7cac9316 | 1010 | ``` |
cc61c64b XL |
1011 | $ cargo test |
1012 | Compiling communicator v0.1.0 (file:///projects/communicator) | |
1013 | error[E0433]: failed to resolve. Use of undeclared type or module `client` | |
1014 | --> src/lib.rs:9:9 | |
1015 | | | |
1016 | 9 | client::connect(); | |
abe05a73 | 1017 | | ^^^^^^ Use of undeclared type or module `client` |
cc61c64b XL |
1018 | ``` |
1019 | ||
1020 | The compilation failed, but why? We don’t need to place `communicator::` in | |
1021 | front of the function like we did in *src/main.rs* because we are definitely | |
1022 | within the `communicator` library crate here. The reason is that paths are | |
1023 | always relative to the current module, which here is `tests`. The only | |
1024 | exception is in a `use` statement, where paths are relative to the crate root | |
1025 | by default. Our `tests` module needs the `client` module in its scope! | |
1026 | ||
7cac9316 XL |
1027 | So how do we get back up one module in the module hierarchy to call the |
1028 | `client::connect` function in the `tests` module? In the `tests` module, we can | |
1029 | either use leading colons to let Rust know that we want to start from the root | |
1030 | and list the whole path, like this: | |
cc61c64b | 1031 | |
7cac9316 | 1032 | ``` |
cc61c64b XL |
1033 | ::client::connect(); |
1034 | ``` | |
1035 | ||
7cac9316 XL |
1036 | Or, we can use `super` to move up one module in the hierarchy from our current |
1037 | module, like this: | |
cc61c64b | 1038 | |
7cac9316 | 1039 | ``` |
cc61c64b XL |
1040 | super::client::connect(); |
1041 | ``` | |
1042 | ||
7cac9316 XL |
1043 | These two options don’t look that different in this example, but if you’re |
1044 | deeper in a module hierarchy, starting from the root every time would make your | |
1045 | code lengthy. In those cases, using `super` to get from the current module to | |
1046 | sibling modules is a good shortcut. Plus, if you’ve specified the path from the | |
1047 | root in many places in your code and then you rearrange your modules by moving | |
1048 | a subtree to another place, you’d end up needing to update the path in several | |
1049 | places, which would be tedious. | |
cc61c64b | 1050 | |
7cac9316 XL |
1051 | It would also be annoying to have to type `super::` in each test, but you’ve |
1052 | already seen the tool for that solution: `use`! The `super::` functionality | |
1053 | changes the path you give to `use` so it is relative to the parent module | |
1054 | instead of to the root module. | |
cc61c64b XL |
1055 | |
1056 | For these reasons, in the `tests` module especially, `use super::something` is | |
7cac9316 | 1057 | usually the best solution. So now our test looks like this: |
cc61c64b | 1058 | |
7cac9316 | 1059 | Filename: src/lib.rs |
cc61c64b | 1060 | |
7cac9316 | 1061 | ``` |
cc61c64b XL |
1062 | #[cfg(test)] |
1063 | mod tests { | |
1064 | use super::client; | |
1065 | ||
1066 | #[test] | |
1067 | fn it_works() { | |
1068 | client::connect(); | |
1069 | } | |
1070 | } | |
1071 | ``` | |
1072 | ||
7cac9316 XL |
1073 | When we run `cargo test` again, the test will pass and the first part of the |
1074 | test result output will be the following: | |
cc61c64b | 1075 | |
7cac9316 | 1076 | ``` |
cc61c64b XL |
1077 | $ cargo test |
1078 | Compiling communicator v0.1.0 (file:///projects/communicator) | |
1079 | Running target/debug/communicator-92007ddb5330fa5a | |
1080 | ||
1081 | running 1 test | |
1082 | test tests::it_works ... ok | |
1083 | ||
1084 | test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured | |
1085 | ``` | |
1086 | ||
1087 | ## Summary | |
1088 | ||
7cac9316 XL |
1089 | Now you know some new techniques for organizing your code! Use these techniques |
1090 | to group related functionality together, keep files from becoming too long, and | |
1091 | present a tidy public API to your library users. | |
1092 | ||
1093 | Next, we’ll look at some collection data structures in the standard library | |
1094 | that you can use in your nice, neat code! | |
cc61c64b | 1095 |