diff --git a/rustbook-en/ci/dictionary.txt b/rustbook-en/ci/dictionary.txt index 6329ed12..e2f5f670 100644 --- a/rustbook-en/ci/dictionary.txt +++ b/rustbook-en/ci/dictionary.txt @@ -2,8 +2,6 @@ personal_ws-1.1 en 0 utf-8 abcabcabc abcd abcdefghijklmnopqrstuvwxyz -adaptor -adaptors AddAssign Addr adfb diff --git a/rustbook-en/dot/trpl04-05.dot b/rustbook-en/dot/trpl04-05.dot index ca1f7e06..ccdad725 100644 --- a/rustbook-en/dot/trpl04-05.dot +++ b/rustbook-en/dot/trpl04-05.dot @@ -1,32 +1,38 @@ digraph { - rankdir=LR; - overlap=false; - dpi=300.0; - node [shape="plaintext"]; - - table0[label=< - - - -
s
namevalue
ptr
>]; - table1[label=< - - - - - -
s1
namevalue
ptr
len5
capacity5
>]; - table2[label=< - - - - - - -
indexvalue
0h
1e
2l
3l
4o
>]; - - edge[tailclip="false"]; - table1:pointer:c -> table2:pointee; - table0:borrower:c -> table1:borrowee; -} - + rankdir = LR; + overlap = false; + dpi = 300.0; + node [shape = "plaintext";]; + + s [label = < + + + + + +
s
namevalue
ptr
len4
capacity4
>;]; + + subgraph cluster_heap { + peripheries = 0; + rank = "same"; + + hello [label = < + + + + + + +
indexvalue
0h
1e
2l
3l
4o
>;]; + + ahoy [label = < + + + + + +
indexvalue
0a
1h
2o
3y
>;]; + } + + s -> ahoy [tailport = "pointer:c"; headport = "pointee"; tailclip = false;]; +} \ No newline at end of file diff --git a/rustbook-en/dot/trpl04-06.dot b/rustbook-en/dot/trpl04-06.dot index a23f179a..ca1f7e06 100644 --- a/rustbook-en/dot/trpl04-06.dot +++ b/rustbook-en/dot/trpl04-06.dot @@ -5,37 +5,28 @@ digraph { node [shape="plaintext"]; table0[label=< - + - - +
world
s
namevalue
ptr
len5
ptr
>]; - - table3[label=< - + table1[label=<
s
+ - - - + + +
s1
namevalue
ptr
len11
capacity11
ptr
len5
capacity5
>]; - table4[label=< + table2[label=<
- - - - - -
indexvalue
0h
1e
2l
3l
4o
5
6w
7o
8r
9l
10d
>]; - edge[tailclip="false"]; - table0:pointer2:c -> table4:pointee2; - table3:pointer:c -> table4:pointee; + table1:pointer:c -> table2:pointee; + table0:borrower:c -> table1:borrowee; } diff --git a/rustbook-en/dot/trpl04-07.dot b/rustbook-en/dot/trpl04-07.dot new file mode 100644 index 00000000..a23f179a --- /dev/null +++ b/rustbook-en/dot/trpl04-07.dot @@ -0,0 +1,41 @@ +digraph { + rankdir=LR; + overlap=false; + dpi=300.0; + node [shape="plaintext"]; + + table0[label=< + + + + +
world
namevalue
ptr
len5
>]; + + table3[label=< + + + + + +
s
namevalue
ptr
len11
capacity11
>]; + table4[label=< + + + + + + + + + + + + +
indexvalue
0h
1e
2l
3l
4o
5
6w
7o
8r
9l
10d
>]; + + + edge[tailclip="false"]; + table0:pointer2:c -> table4:pointee2; + table3:pointer:c -> table4:pointee; +} + diff --git a/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/Cargo.lock b/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/Cargo.lock new file mode 100644 index 00000000..2aa4918e --- /dev/null +++ b/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "ownership" +version = "0.1.0" + diff --git a/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/Cargo.toml b/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/Cargo.toml new file mode 100644 index 00000000..e8847526 --- /dev/null +++ b/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ownership" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/src/main.rs b/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/src/main.rs new file mode 100644 index 00000000..b2d0846c --- /dev/null +++ b/rustbook-en/listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/src/main.rs @@ -0,0 +1,8 @@ +fn main() { + // ANCHOR: here + let mut s = String::from("hello"); + s = String::from("ahoy"); + + println!("{s}, world!"); + // ANCHOR_END: here +} diff --git a/rustbook-en/src/ch03-02-data-types.md b/rustbook-en/src/ch03-02-data-types.md index 2cfc156e..84af90e3 100644 --- a/rustbook-en/src/ch03-02-data-types.md +++ b/rustbook-en/src/ch03-02-data-types.md @@ -271,14 +271,14 @@ brackets: {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-13-arrays/src/main.rs}} ``` -Arrays are useful when you want your data allocated on the stack rather than -the heap (we will discuss the stack and the heap more in [Chapter -4][stack-and-heap]) or when you want to ensure you always have a -fixed number of elements. An array isn’t as flexible as the vector type, -though. A *vector* is a similar collection type provided by the standard -library that *is* allowed to grow or shrink in size. If you’re unsure whether -to use an array or a vector, chances are you should use a vector. [Chapter -8][vectors] discusses vectors in more detail. +Arrays are useful when you want your data allocated on the stack, the same as +the other types we have seen so far, rather than the heap (we will discuss the +stack and the heap more in [Chapter 4][stack-and-heap]) or when +you want to ensure you always have a fixed number of elements. An array isn’t as +flexible as the vector type, though. A *vector* is a similar collection type +provided by the standard library that *is* allowed to grow or shrink in size. If +you’re unsure whether to use an array or a vector, chances are you should use a +vector. [Chapter 8][vectors] discusses vectors in more detail. However, arrays are more useful when you know the number of elements will not need to change. For example, if you were using the names of the month in a diff --git a/rustbook-en/src/ch04-01-what-is-ownership.md b/rustbook-en/src/ch04-01-what-is-ownership.md index 5249c2dd..5ef7b5f9 100644 --- a/rustbook-en/src/ch04-01-what-is-ownership.md +++ b/rustbook-en/src/ch04-01-what-is-ownership.md @@ -113,12 +113,13 @@ hardcoded into the text of our program. The variable is valid from the point at which it’s declared until the end of the current *scope*. Listing 4-1 shows a program with comments annotating where the variable `s` would be valid. ++ ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}} ``` -Listing 4-1: A variable and the scope in which it is -valid + In other words, there are two important points in time here: @@ -239,12 +240,13 @@ we’ve allocated on the heap. Let’s explore some of those situations now. Multiple variables can interact with the same data in different ways in Rust. Let’s look at an example using an integer in Listing 4-2. ++ ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-02/src/main.rs:here}} ``` -Listing 4-2: Assigning the integer value of variable `x` -to `y` + We can probably guess what this is doing: “bind the value `5` to `x`; then make a copy of the value in `x` and bind it to `y`.” We now have two variables, `x` @@ -354,6 +356,37 @@ In addition, there’s a design choice that’s implied by this: Rust will never automatically create “deep” copies of your data. Therefore, any *automatic* copying can be assumed to be inexpensive in terms of runtime performance. +#### Scope and Assignment + +The inverse of this is true for the relationship between scoping, ownership, and +memory being freed via the `drop` function as well. When you assign a completely +new value to an existing variable, Rust will call `drop` and free the original +value’s memory immediately. Consider this code, for example: + +```rust +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-04b-replacement-drop/src/main.rs:here}} +``` + +We initially declare a variable `s` and bind it to a `String` with the value +`"hello"`. Then we immediately create a new `String` with the value `"ahoy"` and +assign it to `s`. At this point, nothing is referring to the original value on +the heap at all. + +One table s representing the string value on the stack, pointing to
+the second piece of string data (ahoy) on the heap, with the original string
+data (hello) grayed out because it cannot be accessed anymore. + +Figure 4-5: Representation in memory after the initial +value has been replaced in its entirety. + +The original string thus immediately goes out of scope. Rust will run the `drop` +function on it and its memory will be freed right away. When we print the value +at the end, it will be `"ahoy, world!"`. + @@ -429,14 +462,13 @@ assigning a value to a variable. Passing a variable to a function will move or copy, just as assignment does. Listing 4-3 has an example with some annotations showing where variables go into and out of scope. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-03/src/main.rs}} ``` -Listing 4-3: Functions with ownership and scope -annotated + If we tried to use `s` after the call to `takes_ownership`, Rust would throw a compile-time error. These static checks protect us from mistakes. Try adding @@ -449,14 +481,13 @@ Returning values can also transfer ownership. Listing 4-4 shows an example of a function that returns some value, with similar annotations as those in Listing 4-3. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-04/src/main.rs}} ``` -Listing 4-4: Transferring ownership of return -values + The ownership of a variable follows the same pattern every time: assigning a value to another variable moves it. When a variable that includes data on the @@ -471,13 +502,13 @@ from the body of the function that we might want to return as well. Rust does let us return multiple values using a tuple, as shown in Listing 4-5. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-05/src/main.rs}} ``` -Listing 4-5: Returning ownership of parameters + But this is too much ceremony and a lot of work for a concept that should be common. Luckily for us, Rust has a feature for using a value without diff --git a/rustbook-en/src/ch04-02-references-and-borrowing.md b/rustbook-en/src/ch04-02-references-and-borrowing.md index ea2d8d20..05500157 100644 --- a/rustbook-en/src/ch04-02-references-and-borrowing.md +++ b/rustbook-en/src/ch04-02-references-and-borrowing.md @@ -12,23 +12,25 @@ particular type for the life of that reference. Here is how you would define and use a `calculate_length` function that has a reference to an object as a parameter instead of taking ownership of the value: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:all}} ``` + + First, notice that all the tuple code in the variable declaration and the function return value is gone. Second, note that we pass `&s1` into `calculate_length` and, in its definition, we take `&String` rather than `String`. These ampersands represent *references*, and they allow you to refer -to some value without taking ownership of it. Figure 4-5 depicts this concept. +to some value without taking ownership of it. Figure 4-6 depicts this concept. Three tables: the table for s contains only a pointer to the table
 for s1. The table for s1 contains the stack data for s1 and points to the
-string data on the heap. +string data on the heap." src="img/trpl04-06.svg" class="center" /> -Figure 4-5: A diagram of `&String s` pointing at `String +Figure 4-6: A diagram of `&String s` pointing at `String s1` > Note: The opposite of referencing by using `&` is *dereferencing*, which is @@ -67,13 +69,13 @@ to give it back. You don’t own it. So, what happens if we try to modify something we’re borrowing? Try the code in Listing 4-6. Spoiler alert: it doesn’t work! -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-06/src/main.rs}} ``` -Listing 4-6: Attempting to modify a borrowed value + Here’s the error: @@ -89,12 +91,14 @@ allowed to modify something we have a reference to. We can fix the code from Listing 4-6 to allow us to modify a borrowed value with just a few small tweaks that use, instead, a *mutable reference*: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/src/main.rs}} ``` + + First we change `s` to be `mut`. Then we create a mutable reference with `&mut s` where we call the `change` function, and update the function signature to accept a mutable reference with `some_string: &mut String`. This makes it very @@ -104,12 +108,14 @@ Mutable references have one big restriction: if you have a mutable reference to a value, you can have no other references to that value. This code that attempts to create two mutable references to `s` will fail: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/src/main.rs:here}} ``` + + Here’s the error: ```console @@ -198,12 +204,14 @@ reference to the data does. Let’s try to create a dangling reference to see how Rust prevents them with a compile-time error: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-14-dangling-reference/src/main.rs}} ``` + + Here’s the error: ```console @@ -222,12 +230,14 @@ for it to be borrowed from Let’s take a closer look at exactly what’s happening at each stage of our `dangle` code: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs:here}} ``` + + Because `s` is created inside `dangle`, when the code of `dangle` is finished, `s` will be deallocated. But we tried to return a reference to it. That means this reference would be pointing to an invalid `String`. That’s no good! Rust diff --git a/rustbook-en/src/ch04-03-slices.md b/rustbook-en/src/ch04-03-slices.md index 7f8c9b7a..d01d9050 100644 --- a/rustbook-en/src/ch04-03-slices.md +++ b/rustbook-en/src/ch04-03-slices.md @@ -21,14 +21,13 @@ ownership, so this is fine. But what should we return? We don’t really have a way to talk about *part* of a string. However, we could return the index of the end of the word, indicated by a space. Let’s try that, as shown in Listing 4-7. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:here}} ``` -Listing 4-7: The `first_word` function that returns a -byte index value into the `String` parameter + Because we need to go through the `String` element by element and check whether a value is a space, we’ll convert our `String` to an array of bytes using the @@ -73,14 +72,13 @@ because it’s a separate value from the `String`, there’s no guarantee that i will still be valid in the future. Consider the program in Listing 4-8 that uses the `first_word` function from Listing 4-7. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-08/src/main.rs:here}} ``` -Listing 4-8: Storing the result from calling the -`first_word` function and then changing the `String` contents + This program compiles without any errors and would also do so if we used `word` after calling `s.clear()`. Because `word` isn’t connected to the state of `s` @@ -121,15 +119,15 @@ corresponds to `ending_index` minus `starting_index`. So, in the case of `let world = &s[6..11];`, `world` would be a slice that contains a pointer to the byte at index 6 of `s` with a length value of `5`. -Figure 4-6 shows this in a diagram. +Figure 4-7 shows this in a diagram. Three tables: a table representing the stack data of s, which points
 to the byte at index 0 in a table of the string data "hello world" on
 the heap. The third table rep-resents the stack data of the slice world, which
 has a length value of 5 and points to byte 6 of the heap data table. +src="img/trpl04-07.svg" class="center" style="width: 50%;" /> -Figure 4-6: String slice referring to part of a +Figure 4-7: String slice referring to part of a `String` With Rust’s `..` range syntax, if you want to start at index 0, you can drop @@ -176,12 +174,14 @@ let slice = &s[..]; With all this information in mind, let’s rewrite `first_word` to return a slice. The type that signifies “string slice” is written as `&str`: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-18-first-word-slice/src/main.rs:here}} ``` + + We get the index for the end of the word the same way we did in Listing 4-7, by looking for the first occurrence of a space. When we find a space, we return a string slice using the start of the string and the index of the space as the @@ -207,12 +207,14 @@ string. Slices make this bug impossible and let us know we have a problem with our code much sooner. Using the slice version of `first_word` will throw a compile-time error: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-19-slice-error/src/main.rs:here}} ``` + + Here’s the compiler error: ```console @@ -257,12 +259,13 @@ A more experienced Rustacean would write the signature shown in Listing 4-9 instead because it allows us to use the same function on both `&String` values and `&str` values. ++ ```rust,ignore {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-09/src/main.rs:here}} ``` -Listing 4-9: Improving the `first_word` function by using -a string slice for the type of the `s` parameter + If we have a string slice, we can pass that directly. If we have a `String`, we can pass a slice of the `String` or a reference to the `String`. This @@ -273,12 +276,14 @@ Methods”][deref-coercions] section of Chapter 15. Defining a function to take a string slice instead of a reference to a `String` makes our API more general and useful without losing any functionality: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-09/src/main.rs:usage}} ``` + + ### Other Slices String slices, as you might imagine, are specific to strings. But there’s a diff --git a/rustbook-en/src/ch05-01-defining-structs.md b/rustbook-en/src/ch05-01-defining-structs.md index c5db4dc7..df589d34 100644 --- a/rustbook-en/src/ch05-01-defining-structs.md +++ b/rustbook-en/src/ch05-01-defining-structs.md @@ -13,13 +13,13 @@ grouped together. Then, inside curly brackets, we define the names and types of the pieces of data, which we call *fields*. For example, Listing 5-1 shows a struct that stores information about a user account. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs:here}} ``` -Listing 5-1: A `User` struct definition + To use a struct after we’ve defined it, we create an *instance* of that struct by specifying concrete values for each of the fields. We create an instance by @@ -31,14 +31,13 @@ struct definition is like a general template for the type, and instances fill in that template with particular data to create values of the type. For example, we can declare a particular user as shown in Listing 5-2. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs:here}} ``` -Listing 5-2: Creating an instance of the `User` -struct + To get a specific value from a struct, we use dot notation. For example, to access this user’s email address, we use `user1.email`. If the instance is @@ -46,14 +45,13 @@ mutable, we can change a value by using the dot notation and assigning into a particular field. Listing 5-3 shows how to change the value in the `email` field of a mutable `User` instance. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs:here}} ``` -Listing 5-3: Changing the value in the `email` field of a -`User` instance + Note that the entire instance must be mutable; Rust doesn’t allow us to mark only certain fields as mutable. As with any expression, we can construct a new @@ -64,14 +62,13 @@ Listing 5-4 shows a `build_user` function that returns a `User` instance with the given email and username. The `active` field gets the value of `true`, and the `sign_in_count` gets a value of `1`. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs:here}} ``` -Listing 5-4: A `build_user` function that takes an email -and username and returns a `User` instance + It makes sense to name the function parameters with the same name as the struct fields, but having to repeat the `email` and `username` field names and @@ -88,15 +85,13 @@ Listing 5-4, we can use the *field init shorthand* syntax to rewrite `build_user` so it behaves exactly the same but doesn’t have the repetition of `username` and `email`, as shown in Listing 5-5. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs:here}} ``` -Listing 5-5: A `build_user` function that uses field init -shorthand because the `username` and `email` parameters have the same name as -struct fields + Here, we’re creating a new instance of the `User` struct, which has a field named `email`. We want to set the `email` field’s value to the value in the @@ -114,28 +109,25 @@ First, in Listing 5-6 we show how to create a new `User` instance in `user2` regularly, without the update syntax. We set a new value for `email` but otherwise use the same values from `user1` that we created in Listing 5-2. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs:here}} ``` -Listing 5-6: Creating a new `User` instance using all but one of -the values from `user1` + Using struct update syntax, we can achieve the same effect with less code, as shown in Listing 5-7. The syntax `..` specifies that the remaining fields not explicitly set should have the same value as the fields in the given instance. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs:here}} ``` -Listing 5-7: Using struct update syntax to set a new -`email` value for a `User` instance but to use the rest of the values from -`user1` + The code in Listing 5-7 also creates an instance in `user2` that has a different value for `email` but has the same values for the `username`, @@ -154,7 +146,8 @@ Move”][move] section. In this example, we can no longer use `active` and `sign_in_count` values from `user1`, then `user1` would still be valid after creating `user2`. Both `active` and `sign_in_count` are types that implement the `Copy` trait, so the behavior we discussed in the [“Stack-Only -Data: Copy”][copy] section would apply. +Data: Copy”][copy] section would apply. We can still use +`user1.email` in this example, since its value was _not_ moved out. ### Using Tuple Structs Without Named Fields to Create Different Types @@ -169,12 +162,14 @@ To define a tuple struct, start with the `struct` keyword and the struct name followed by the types in the tuple. For example, here we define and use two tuple structs named `Color` and `Point`: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs}} ``` + + Note that the `black` and `origin` values are different types because they’re instances of different tuple structs. Each struct you define is its own type, even though the fields within the struct might have the same types. For @@ -194,12 +189,14 @@ have any data that you want to store in the type itself. We’ll discuss traits in Chapter 10. Here’s an example of declaring and instantiating a unit struct named `AlwaysEqual`: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs}} ``` + + To define `AlwaysEqual`, we use the `struct` keyword, the name we want, and then a semicolon. No need for curly brackets or parentheses! Then we can get an instance of `AlwaysEqual` in the `subject` variable in a similar way: using the @@ -223,7 +220,7 @@ implement them on any type, including unit-like structs. > is valid for as long as the struct is. Let’s say you try to store a reference > in a struct without specifying lifetimes, like the following; this won’t work: > -> Filename: src/main.rs +> > > > @@ -245,6 +242,8 @@ implement them on any type, including unit-like structs. > } > ``` > +> +> > The compiler will complain that it needs lifetime specifiers: > > ```console diff --git a/rustbook-en/src/ch05-02-example-structs.md b/rustbook-en/src/ch05-02-example-structs.md index 1e7c9f7e..392f1bd3 100644 --- a/rustbook-en/src/ch05-02-example-structs.md +++ b/rustbook-en/src/ch05-02-example-structs.md @@ -9,14 +9,13 @@ the width and height of a rectangle specified in pixels and calculate the area of the rectangle. Listing 5-8 shows a short program with one way of doing exactly that in our project’s *src/main.rs*. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs:all}} ``` -Listing 5-8: Calculating the area of a rectangle -specified by separate width and height variables + Now, run this program using `cargo run`: @@ -45,14 +44,13 @@ of Chapter 3: by using tuples. Listing 5-9 shows another version of our program that uses tuples. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-09/src/main.rs}} ``` -Listing 5-9: Specifying the width and height of the -rectangle with a tuple + In one way, this program is better. Tuples let us add a bit of structure, and we’re now passing just one argument. But in another way, this version is less @@ -72,13 +70,13 @@ We use structs to add meaning by labeling the data. We can transform the tuple we’re using into a struct with a name for the whole as well as names for the parts, as shown in Listing 5-10. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-10/src/main.rs}} ``` -Listing 5-10: Defining a `Rectangle` struct + Here we’ve defined a struct and named it `Rectangle`. Inside the curly brackets, we defined the fields as `width` and `height`, both of which have @@ -108,14 +106,13 @@ debugging our program and see the values for all its fields. Listing 5-11 tries using the [`println!` macro][println] as we have used in previous chapters. This won’t work, however. -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs}} ``` -Listing 5-11: Attempting to print a `Rectangle` -instance + When we compile this code, we get an error with this core message: @@ -163,14 +160,13 @@ have to explicitly opt in to make that functionality available for our struct. To do that, we add the outer attribute `#[derive(Debug)]` just before the struct definition, as shown in Listing 5-12. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-12/src/main.rs}} ``` -Listing 5-12: Adding the attribute to derive the `Debug` -trait and printing the `Rectangle` instance using debug formatting + Now when we run the program, we won’t get any errors, and we’ll see the following output: diff --git a/rustbook-en/src/ch05-03-method-syntax.md b/rustbook-en/src/ch05-03-method-syntax.md index d25e55b1..91887210 100644 --- a/rustbook-en/src/ch05-03-method-syntax.md +++ b/rustbook-en/src/ch05-03-method-syntax.md @@ -15,14 +15,13 @@ Let’s change the `area` function that has a `Rectangle` instance as a paramete and instead make an `area` method defined on the `Rectangle` struct, as shown in Listing 5-13. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs}} ``` -Listing 5-13: Defining an `area` method on the -`Rectangle` struct + To define the function within the context of `Rectangle`, we start an `impl` (implementation) block for `Rectangle`. Everything within this `impl` block @@ -65,12 +64,14 @@ Note that we can choose to give a method the same name as one of the struct’s fields. For example, we can define a method on `Rectangle` that is also named `width`: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs:here}} ``` + + Here, we’re choosing to make the `width` method return `true` if the value in the instance’s `width` field is greater than `0` and `false` if the value is `0`: we can use a field within a method of the same name for any purpose. In @@ -141,14 +142,13 @@ within `self` (the first `Rectangle`); otherwise, it should return `false`. That is, once we’ve defined the `can_hold` method, we want to be able to write the program shown in Listing 5-14. -Filename: src/main.rs + ```rust,ignore {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-14/src/main.rs}} ``` -Listing 5-14: Using the as-yet-unwritten `can_hold` -method + The expected output would look like the following because both dimensions of `rect2` are smaller than the dimensions of `rect1`, but `rect3` is wider than @@ -173,14 +173,13 @@ Boolean, and the implementation will check whether the width and height of respectively. Let’s add the new `can_hold` method to the `impl` block from Listing 5-13, shown in Listing 5-15. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-15/src/main.rs:here}} ``` -Listing 5-15: Implementing the `can_hold` method on -`Rectangle` that takes another `Rectangle` instance as a parameter + When we run this code with the `main` function in Listing 5-14, we’ll get our desired output. Methods can take multiple parameters that we add to the @@ -226,12 +225,13 @@ Each struct is allowed to have multiple `impl` blocks. For example, Listing 5-15 is equivalent to the code shown in Listing 5-16, which has each method in its own `impl` block. ++ ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-16/src/main.rs:here}} ``` -Listing 5-16: Rewriting Listing 5-15 using multiple `impl` -blocks + There’s no reason to separate these methods into multiple `impl` blocks here, but this is valid syntax. We’ll see a case in which multiple `impl` blocks are diff --git a/rustbook-en/src/ch13-02-iterators.md b/rustbook-en/src/ch13-02-iterators.md index c99fcd69..4ce9170d 100644 --- a/rustbook-en/src/ch13-02-iterators.md +++ b/rustbook-en/src/ch13-02-iterators.md @@ -111,7 +111,7 @@ trait. Some of these methods call the `next` method in their definition, which is why you’re required to implement the `next` method when implementing the `Iterator` trait. -Methods that call `next` are called *consuming adaptors*, because calling them +Methods that call `next` are called *consuming adapters*, because calling them uses up the iterator. One example is the `sum` method, which takes ownership of the iterator and iterates through the items by repeatedly calling `next`, thus consuming the iterator. As it iterates through, it adds each item to a running @@ -131,17 +131,17 @@ ownership of the iterator we call it on. ### Methods that Produce Other Iterators -*Iterator adaptors* are methods defined on the `Iterator` trait that don’t +*Iterator adapters* are methods defined on the `Iterator` trait that don’t consume the iterator. Instead, they produce different iterators by changing some aspect of the original iterator. -Listing 13-14 shows an example of calling the iterator adaptor method `map`, +Listing 13-14 shows an example of calling the iterator adapter method `map`, which takes a closure to call on each item as the items are iterated through. The `map` method returns a new iterator that produces the modified items. The closure here creates a new iterator in which each item from the vector will be incremented by 1: -+ ```rust,not_desired_behavior {{#rustdoc_include ../listings/ch13-functional-features/listing-13-14/src/main.rs:here}} @@ -156,7 +156,7 @@ However, this code produces a warning: ``` The code in Listing 13-14 doesn’t do anything; the closure we’ve specified -never gets called. The warning reminds us why: iterator adaptors are lazy, and +never gets called. The warning reminds us why: iterator adapters are lazy, and we need to consume the iterator here. To fix this warning and consume the iterator, we’ll use the `collect` method, @@ -181,9 +181,9 @@ on each item. This is a great example of how closures let you customize some behavior while reusing the iteration behavior that the `Iterator` trait provides. -You can chain multiple calls to iterator adaptors to perform complex actions in +You can chain multiple calls to iterator adapters to perform complex actions in a readable way. But because all iterators are lazy, you have to call one of the -consuming adaptor methods to get results from calls to iterator adaptors. +consuming adapter methods to get results from calls to iterator adapters. ### Using Closures that Capture Their Environment diff --git a/rustbook-en/src/ch13-03-improving-our-io-project.md b/rustbook-en/src/ch13-03-improving-our-io-project.md index 4c1a5084..c560bc11 100644 --- a/rustbook-en/src/ch13-03-improving-our-io-project.md +++ b/rustbook-en/src/ch13-03-improving-our-io-project.md @@ -116,7 +116,7 @@ value we want to put in the `query` field of `Config`. If `next` returns a not enough arguments were given and we return early with an `Err` value. We do the same thing for the `file_path` value. -### Making Code Clearer with Iterator Adaptors +### Making Code Clearer with Iterator Adapters We can also take advantage of iterators in the `search` function in our I/O project, which is reproduced here in Listing 13-21 as it was in Listing 12-19: @@ -129,14 +129,14 @@ project, which is reproduced here in Listing 13-21 as it was in Listing 12-19: -We can write this code in a more concise way using iterator adaptor methods. +We can write this code in a more concise way using iterator adapter methods. Doing so also lets us avoid having a mutable intermediate `results` vector. The functional programming style prefers to minimize the amount of mutable state to make code clearer. Removing the mutable state might enable a future enhancement to make searching happen in parallel, because we wouldn’t have to manage concurrent access to the `results` vector. Listing 13-22 shows this change: -+ ```rust,ignore {{#rustdoc_include ../listings/ch13-functional-features/listing-13-22/src/lib.rs:here}} @@ -146,7 +146,7 @@ concurrent access to the `results` vector. Listing 13-22 shows this change: Recall that the purpose of the `search` function is to return all lines in `contents` that contain the `query`. Similar to the `filter` example in Listing -13-16, this code uses the `filter` adaptor to keep only the lines that +13-16, this code uses the `filter` adapter to keep only the lines that `line.contains(query)` returns `true` for. We then collect the matching lines into another vector with `collect`. Much simpler! Feel free to make the same change to use iterator methods in the `search_case_insensitive` function as @@ -158,7 +158,7 @@ The next logical question is which style you should choose in your own code and why: the original implementation in Listing 13-21 or the version using iterators in Listing 13-22. Most Rust programmers prefer to use the iterator style. It’s a bit tougher to get the hang of at first, but once you get a feel -for the various iterator adaptors and what they do, iterators can be easier to +for the various iterator adapters and what they do, iterators can be easier to understand. Instead of fiddling with the various bits of looping and building new vectors, the code focuses on the high-level objective of the loop. This abstracts away some of the commonplace code so it’s easier to see the concepts diff --git a/rustbook-en/src/ch13-04-performance.md b/rustbook-en/src/ch13-04-performance.md index 5d09bf29..0dbc7420 100644 --- a/rustbook-en/src/ch13-04-performance.md +++ b/rustbook-en/src/ch13-04-performance.md @@ -65,7 +65,7 @@ multiply the values together, sum all the results, and shift the bits in the sum `qlp_shift` bits to the right. Calculations in applications like audio decoders often prioritize performance -most highly. Here, we’re creating an iterator, using two adaptors, and then +most highly. Here, we’re creating an iterator, using two adapters, and then consuming the value. What assembly code would this Rust code compile to? Well, as of this writing, it compiles down to the same assembly you’d write by hand. There’s no loop at all corresponding to the iteration over the values in diff --git a/rustbook-en/src/img/trpl04-05.svg b/rustbook-en/src/img/trpl04-05.svg index b4bf2ebe..f3c6e8a8 100644 --- a/rustbook-en/src/img/trpl04-05.svg +++ b/rustbook-en/src/img/trpl04-05.svg @@ -1,87 +1,95 @@ - - + - -%3 - - - -table0 - -s - -name - -value - -ptr - - - - -table1 - -s1 - -name - -value - -ptr - - -len - -5 - -capacity - -5 + viewBox="0.00 0.00 1038.00 1342.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + + + +cluster_heap - - -table0:c->table1:borrowee - - + + +s + +s + +name + +value + +ptr + + +len + +4 + +capacity + +4 - + -table2 - -index - -value - -0 - -h - -1 - -e - -2 - -l - -3 - -l - -4 - -o +ahoy + +index + +value + +0 + +a + +1 + +h + +2 + +o + +3 + +y - + -table1:c->table2:pointee - - +s:c->ahoy:pointee + + + + + +hello + + +index + +value + +0 + +h + +1 + +e + +2 + +l + +3 + +l + +4 + +o diff --git a/rustbook-en/src/img/trpl04-06.svg b/rustbook-en/src/img/trpl04-06.svg index e64415fe..b4bf2ebe 100644 --- a/rustbook-en/src/img/trpl04-06.svg +++ b/rustbook-en/src/img/trpl04-06.svg @@ -5,111 +5,83 @@ --> - + viewBox="0.00 0.00 1500.00 650.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + %3 - + table0 - -world - -name - -value - -ptr - - -len - -5 + +s + +name + +value + +ptr + - - -table4 - -index - -value - -0 - -h - -1 - -e - -2 - -l - -3 - -l - -4 - -o - -5 - - - -6 - -w - -7 - -o - -8 - -r - -9 - -l - -10 - -d - - - -table0:c->table4:pointee2 - - - - + -table3 - -s - -name - -value - -ptr - - -len - -11 - -capacity - -11 +table1 + +s1 + +name + +value + +ptr + + +len + +5 + +capacity + +5 - + -table3:c->table4:pointee - - +table0:c->table1:borrowee + + + + + +table2 + +index + +value + +0 + +h + +1 + +e + +2 + +l + +3 + +l + +4 + +o + + + +table1:c->table2:pointee + + diff --git a/rustbook-en/src/img/trpl04-07.svg b/rustbook-en/src/img/trpl04-07.svg new file mode 100644 index 00000000..e64415fe --- /dev/null +++ b/rustbook-en/src/img/trpl04-07.svg @@ -0,0 +1,115 @@ + + + + + + +%3 + + + +table0 + +world + +name + +value + +ptr + + +len + +5 + + + +table4 + +index + +value + +0 + +h + +1 + +e + +2 + +l + +3 + +l + +4 + +o + +5 + + + +6 + +w + +7 + +o + +8 + +r + +9 + +l + +10 + +d + + + +table0:c->table4:pointee2 + + + + + +table3 + +s + +name + +value + +ptr + + +len + +11 + +capacity + +11 + + + +table3:c->table4:pointee + + + + +