Add some listing numbers to code blocks

This commit is contained in:
Carol (Nichols || Goulding) 2016-11-23 12:00:35 -05:00
parent 347d1e448a
commit 985b93c2e9
3 changed files with 120 additions and 44 deletions

View File

@ -24,7 +24,8 @@ To define a struct, we enter the keyword `struct` and give the whole struct a
name. A structs name should describe what the significance is of these pieces
of data being grouped together. Then, inside curly braces, we define the names
of the pieces of data, which we call *fields*, and specify each fields type.
For example, a struct to store information about a user account might look like:
For example, Listing 5-1 shows a struct to store information about a user
account:
```rust
struct User {
@ -35,15 +36,19 @@ struct User {
}
```
To use a struct, we create an *instance* of that struct by specifying concrete
values for each of the fields. Creating an instance is done by stating the name
of the struct, then curly braces with `key: value` pairs inside it where the
keys are the names of the fields and the values are the data we want to store
in those fields. The fields dont have to be specified in the same order in
which the struct declared them. In other words, the 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 like this:
<caption>
Listing 5-1: A `User` struct definition
</caption>
To use a struct once we've defined it, we create an *instance* of that struct
by specifying concrete values for each of the fields. Creating an instance is
done by stating the name of the struct, then curly braces with `key: value`
pairs inside it where the keys are the names of the fields and the values are
the data we want to store in those fields. The fields dont have to be
specified in the same order in which the struct declared them. In other words,
the 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 like this:
```rust
let user1 = User {
@ -65,8 +70,8 @@ refactor our program until were using structs instead.
Lets make a new binary project with Cargo called *rectangles* that will take
the length and width of a rectangle specified in pixels and will calculate the
area of the rectangle. Heres a short program that has one way of doing just
that to put into our projects *src/main.rs*:
area of the rectangle. Listing 5-2 has a short program with one way of doing
just that in our projects *src/main.rs*:
Filename: src/main.rs
@ -86,6 +91,11 @@ fn area(length: u32, width: u32) -> u32 {
}
```
<caption>
Listing 5-2: Calculating the area of a rectangle specified by its length and
width in separate variables
</caption>
Lets try running this program with `cargo run`:
```text
@ -110,8 +120,8 @@ function takes two arguments. The arguments are related, but thats not
expressed anywhere in our program itself. It would be more readable and more
manageable to group length and width together.
Weve already discussed one way we might do that in Chapter 3: tuples. Heres a
version of our program which uses tuples:
Weve already discussed one way we might do that in Chapter 3: tuples. Listing
5-3 has a version of our program which uses tuples:
Filename: src/main.rs
@ -130,6 +140,10 @@ fn area(dimensions: (u32, u32)) -> u32 {
}
```
<caption>
Listing 5-3: Specifying the length and width of the rectangle with a tuple
</caption>
<!-- I will add ghosting & wingdings once we're in libreoffice /Carol -->
In one way, this is a little better. Tuples let us add a bit of structure, and
@ -155,7 +169,8 @@ in our code.
### Refactoring with Structs: Adding More Meaning
Here is where we bring in structs. We can transform our tuple into a data type
with a name for the whole as well as names for the parts:
with a name for the whole as well as names for the parts, as shown in Listing
5-4:
Filename: src/main.rs
@ -179,6 +194,10 @@ fn area(rectangle: &Rectangle) -> u32 {
}
```
<caption>
Listing 5-4: Defining a `Rectangle` struct
</caption>
<!-- Will add ghosting & wingdings once we're in libreoffice /Carol -->
Here weve defined a struct and given it the name `Rectangle`. Inside the `{}`
@ -202,8 +221,8 @@ index values of `0` and `1`. This is a win for clarity.
### Adding Useful Functionality with Derived Traits
Itd be nice to be able to print out an instance of our `Rectangle` while were
debugging our program and see the values for all its fields. Lets try using
the `println!` macro as we have been and see what happens:
debugging our program and see the values for all its fields. Listing 5-5 tries
using the `println!` macro as we have been:
Filename: src/main.rs
@ -220,6 +239,10 @@ fn main() {
}
```
<caption>
Listing 5-5: Attempting to print a `Rectangle` instance
</caption>
If we run this, we get an error with this core message:
```text
@ -266,7 +289,7 @@ crate, add `#[derive(Debug)]` or manually implement it
Rust *does* include functionality to print out debugging information, but we
have to explicitly opt-in to having that functionality be available for our
struct. To do that, we add the annotation `#[derive(Debug)]` just before our
struct definition. Now our program looks like this:
struct definition, as shown in Listing 5-6. Now our program looks like this:
```rust
#[derive(Debug)]
@ -282,6 +305,11 @@ fn main() {
}
```
<caption>
Listing 5-6: Adding the annotation to derive the `Debug` trait and printing the
`Rectangle` instance using debug formatting
</caption>
At this point, if we run this program, we wont get any errors and well see
the following output:
@ -328,7 +356,8 @@ represents the instance of the struct that the method is being called on.
### Defining Methods
Lets change our `area` function that takes a `Rectangle` instance as an
argument and instead make an `area` method defined on the `Rectangle` struct:
argument and instead make an `area` method defined on the `Rectangle` struct,
as shown in Listing 5-7:
```rust
#[derive(Debug)]
@ -353,6 +382,10 @@ fn main() {
}
```
<caption>
Listing 5-7: Defining an `area` method on the `Rectangle` struct
</caption>
<!-- Will add ghosting and wingdings here in libreoffice /Carol -->
In order to make the function be defined within the context of `Rectangle`, we
@ -425,7 +458,7 @@ Lets practice some more with methods by implementing a second method on our
`Rectangle` struct. This time, wed like for an instance of `Rectangle` to take
another instance of `Rectangle` and return `true` if the second rectangle could
fit completely within `self` and `false` if it would not. That is, if we run
this code:
the code in Listing 5-8, once we've defined the `can_hold` method:
```rust,ignore
fn main() {
@ -438,6 +471,10 @@ fn main() {
}
```
<caption>
Listing 5-8: Demonstration of using the as-yet-unwritten `can_hold` method
</caption>
We want to see this output, since both of `rect2`s dimensions are smaller than
`rect1`s, but `rect3` is wider than `rect1`:
@ -456,7 +493,8 @@ would mean wed need a mutable borrow) and we want `main` to keep ownership of
`rect2` so that we could use it again after calling this method. The return
value of `can_hold` will be a boolean, and the implementation will check to see
if `self`s length and width are both greater than the length and width of the
other `Rectangle`, respectively. Lets write that code!
other `Rectangle`, respectively. Lets add this new method to the `impl` block
from Listing 5-7:
```
impl Rectangle {
@ -472,7 +510,7 @@ impl Rectangle {
<!-- Will add ghosting here in libreoffice /Carol -->
If we run this with the `main` from earlier, we will get our desired output!
If we run this with the `main` from Listing 5-8, we will get our desired output!
Methods can take multiple arguments that we add to the signature after the
`self` parameter, and those arguments work just like arguments in functions do.

View File

@ -21,7 +21,8 @@ To define a struct, we enter the keyword `struct` and give the whole struct a
name. A structs name should describe what the significance is of these pieces
of data being grouped together. Then, inside curly braces, we define the names
of the pieces of data, which we call *fields*, and specify each fields type.
For example, a struct to store information about a user account might look like:
For example, Listing 5-1 shows a struct to store information about a user
account:
```rust
struct User {
@ -32,15 +33,19 @@ struct User {
}
```
To use a struct, we create an *instance* of that struct by specifying concrete
values for each of the fields. Creating an instance is done by stating the name
of the struct, then curly braces with `key: value` pairs inside it where the
keys are the names of the fields and the values are the data we want to store
in those fields. The fields dont have to be specified in the same order in
which the struct declared them. In other words, the 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 like this:
<caption>
Listing 5-1: A `User` struct definition
</caption>
To use a struct once we've defined it, we create an *instance* of that struct
by specifying concrete values for each of the fields. Creating an instance is
done by stating the name of the struct, then curly braces with `key: value`
pairs inside it where the keys are the names of the fields and the values are
the data we want to store in those fields. The fields dont have to be
specified in the same order in which the struct declared them. In other words,
the 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 like this:
```rust
# struct User {
@ -69,8 +74,8 @@ refactor our program until were using structs instead.
Lets make a new binary project with Cargo called *rectangles* that will take
the length and width of a rectangle specified in pixels and will calculate the
area of the rectangle. Heres a short program that has one way of doing just
that to put into our projects *src/main.rs*:
area of the rectangle. Listing 5-2 has a short program with one way of doing
just that in our projects *src/main.rs*:
<span class="filename">Filename: src/main.rs</span>
@ -90,6 +95,11 @@ fn area(length: u32, width: u32) -> u32 {
}
```
<caption>
Listing 5-2: Calculating the area of a rectangle specified by its length and
width in separate variables
</caption>
Lets try running this program with `cargo run`:
```text
@ -114,8 +124,8 @@ function takes two arguments. The arguments are related, but thats not
expressed anywhere in our program itself. It would be more readable and more
manageable to group length and width together.
Weve already discussed one way we might do that in Chapter 3: tuples. Heres a
version of our program which uses tuples:
Weve already discussed one way we might do that in Chapter 3: tuples. Listing
5-3 has a version of our program which uses tuples:
<span class="filename">Filename: src/main.rs</span>
@ -134,6 +144,10 @@ fn area(dimensions: (u32, u32)) -> u32 {
}
```
<caption>
Listing 5-3: Specifying the length and width of the rectangle with a tuple
</caption>
<!-- I will add ghosting & wingdings once we're in libreoffice /Carol -->
In one way, this is a little better. Tuples let us add a bit of structure, and
@ -159,7 +173,8 @@ in our code.
### Refactoring with Structs: Adding More Meaning
Here is where we bring in structs. We can transform our tuple into a data type
with a name for the whole as well as names for the parts:
with a name for the whole as well as names for the parts, as shown in Listing
5-4:
<span class="filename">Filename: src/main.rs</span>
@ -183,6 +198,10 @@ fn area(rectangle: &Rectangle) -> u32 {
}
```
<caption>
Listing 5-4: Defining a `Rectangle` struct
</caption>
<!-- Will add ghosting & wingdings once we're in libreoffice /Carol -->
Here weve defined a struct and given it the name `Rectangle`. Inside the `{}`
@ -206,8 +225,8 @@ index values of `0` and `1`. This is a win for clarity.
### Adding Useful Functionality with Derived Traits
Itd be nice to be able to print out an instance of our `Rectangle` while were
debugging our program and see the values for all its fields. Lets try using
the `println!` macro as we have been and see what happens:
debugging our program and see the values for all its fields. Listing 5-5 tries
using the `println!` macro as we have been:
<span class="filename">Filename: src/main.rs</span>
@ -224,6 +243,10 @@ fn main() {
}
```
<caption>
Listing 5-5: Attempting to print a `Rectangle` instance
</caption>
If we run this, we get an error with this core message:
```text
@ -270,7 +293,7 @@ crate, add `#[derive(Debug)]` or manually implement it
Rust *does* include functionality to print out debugging information, but we
have to explicitly opt-in to having that functionality be available for our
struct. To do that, we add the annotation `#[derive(Debug)]` just before our
struct definition. Now our program looks like this:
struct definition, as shown in Listing 5-6. Now our program looks like this:
```rust
#[derive(Debug)]
@ -286,6 +309,11 @@ fn main() {
}
```
<caption>
Listing 5-6: Adding the annotation to derive the `Debug` trait and printing the
`Rectangle` instance using debug formatting
</caption>
At this point, if we run this program, we wont get any errors and well see
the following output:

View File

@ -11,7 +11,8 @@ represents the instance of the struct that the method is being called on.
### Defining Methods
Lets change our `area` function that takes a `Rectangle` instance as an
argument and instead make an `area` method defined on the `Rectangle` struct:
argument and instead make an `area` method defined on the `Rectangle` struct,
as shown in Listing 5-7:
```rust
#[derive(Debug)]
@ -36,6 +37,10 @@ fn main() {
}
```
<caption>
Listing 5-7: Defining an `area` method on the `Rectangle` struct
</caption>
<!-- Will add ghosting and wingdings here in libreoffice /Carol -->
In order to make the function be defined within the context of `Rectangle`, we
@ -124,7 +129,7 @@ Lets practice some more with methods by implementing a second method on our
`Rectangle` struct. This time, wed like for an instance of `Rectangle` to take
another instance of `Rectangle` and return `true` if the second rectangle could
fit completely within `self` and `false` if it would not. That is, if we run
this code:
the code in Listing 5-8, once we've defined the `can_hold` method:
```rust,ignore
fn main() {
@ -137,6 +142,10 @@ fn main() {
}
```
<caption>
Listing 5-8: Demonstration of using the as-yet-unwritten `can_hold` method
</caption>
We want to see this output, since both of `rect2`s dimensions are smaller than
`rect1`s, but `rect3` is wider than `rect1`:
@ -155,7 +164,8 @@ would mean wed need a mutable borrow) and we want `main` to keep ownership of
`rect2` so that we could use it again after calling this method. The return
value of `can_hold` will be a boolean, and the implementation will check to see
if `self`s length and width are both greater than the length and width of the
other `Rectangle`, respectively. Lets write that code!
other `Rectangle`, respectively. Lets add this new method to the `impl` block
from Listing 5-7:
```rust
# #[derive(Debug)]
@ -177,7 +187,7 @@ impl Rectangle {
<!-- Will add ghosting here in libreoffice /Carol -->
If we run this with the `main` from earlier, we will get our desired output!
If we run this with the `main` from Listing 5-8, we will get our desired output!
Methods can take multiple arguments that we add to the signature after the
`self` parameter, and those arguments work just like arguments in functions do.