mirror of https://github.com/rust-lang/book
fancy quotes
This commit is contained in:
parent
f747b3ddcb
commit
06485fb007
|
@ -22,9 +22,9 @@ can find a list of the keywords in Appendix A.
|
|||
|
||||
## Identifiers
|
||||
|
||||
We're going to be explaining a bunch of concepts in this book: variables,
|
||||
We’re going to be explaining a bunch of concepts in this book: variables,
|
||||
functions, structs, lots of things. All of these things need names. A name
|
||||
in Rust is called an "identifier," and can be made up of any nonempty ASCII
|
||||
in Rust is called an “identifier,” and can be made up of any nonempty ASCII
|
||||
string, with some restrictions:
|
||||
|
||||
Either:
|
||||
|
@ -40,9 +40,9 @@ or:
|
|||
|
||||
### Raw identifiers
|
||||
|
||||
Sometimes, you may need to use a name that's a keyword for another purpose.
|
||||
Sometimes, you may need to use a name that’s a keyword for another purpose.
|
||||
Maybe you need to call a function named *match* that is coming from a C
|
||||
library, where 'match' is not a keyword. To do this, you can use a "raw identifier."
|
||||
library, where ‘match’ is not a keyword. To do this, you can use a “raw identifier.”
|
||||
Raw identifiers start with `r#`:
|
||||
|
||||
```rust,ignore
|
||||
|
@ -52,4 +52,4 @@ let r#fn = "this variable is named 'fn' even though that's a keyword";
|
|||
r#match();
|
||||
```
|
||||
|
||||
You won't need raw identifiers often, but when you do, you *really* need them.
|
||||
You won’t need raw identifiers often, but when you do, you *really* need them.
|
||||
|
|
|
@ -101,15 +101,15 @@ which you’d use `isize` or `usize` is when indexing some sort of collection.
|
|||
|
||||
##### Integer Overflow
|
||||
|
||||
Let's say that you have a `u8`, which can hold values between zero and `255`.
|
||||
What happens if you try to change it to `256`? This is called "integer
|
||||
overflow", and Rust has some interesting rules around this behavior. When
|
||||
Let’s say that you have a `u8`, which can hold values between zero and `255`.
|
||||
What happens if you try to change it to `256`? This is called “integer
|
||||
overflow”, and Rust has some interesting rules around this behavior. When
|
||||
compiling in debug mode, Rust checks for this kind of issue and will cause
|
||||
your program to *panic*, which is the term Rust uses when a program exits
|
||||
with an error. We'll discuss panics more in Chapter 9.
|
||||
with an error. We’ll discuss panics more in Chapter 9.
|
||||
|
||||
In release builds, Rust does not check for overflow, and instead will
|
||||
do something called "two's complement wrapping." In short, `256` becomes
|
||||
do something called “two’s complement wrapping.” In short, `256` becomes
|
||||
`0`, `257` becomes `1`, etc. Relying on overflow is considered an error,
|
||||
even if this behavior happens. If you want this behavior explicitly, the
|
||||
standard library has a type, `Wrapping`, that provides it explicitly.
|
||||
|
@ -326,12 +326,12 @@ example:
|
|||
let a: [i32; 5] = [1, 2, 3, 4, 5];
|
||||
```
|
||||
|
||||
First, there's square brackets; they look like the syntax for creating an
|
||||
array. Inside, there's two pieces of information, separated by a semicolon.
|
||||
First, there’s square brackets; they look like the syntax for creating an
|
||||
array. Inside, there’s two pieces of information, separated by a semicolon.
|
||||
The first is the type of each element of the array. Since all elements have
|
||||
the same type, we only need to list it once. After the semicolon, there's
|
||||
the same type, we only need to list it once. After the semicolon, there’s
|
||||
a number that indicates the length of the array. Since an array has a fixed size,
|
||||
this number is always the same, even if the array's elements are modified, it
|
||||
this number is always the same, even if the array’s elements are modified, it
|
||||
cannot grow or shrink.
|
||||
|
||||
##### Accessing Array Elements
|
||||
|
|
|
@ -160,7 +160,7 @@ let hello = &s[0..=4];
|
|||
let world = &s[6..=10];
|
||||
```
|
||||
|
||||
The `=` means that we're including the last number, if that helps you remember
|
||||
The `=` means that we’re including the last number, if that helps you remember
|
||||
the difference between `..` and `..=`.
|
||||
|
||||
We can create slices using a range within brackets by specifying
|
||||
|
|
|
@ -5,12 +5,12 @@ know about at this location in the code? What functions am I allowed to call?
|
|||
What does this variable refer to?
|
||||
|
||||
Rust has a number of features related to scopes. This is sometimes called
|
||||
"the module system", but it encompases more than just modules:
|
||||
“the module system”, but it encompases more than just modules:
|
||||
|
||||
* *Packages* are a Cargo feature that let you build, test, and share crates.
|
||||
* *Crates* are a tree of modules that produce a library or executable.
|
||||
* *Modules* and the *use* keyword let you control the scope and privacy of paths.
|
||||
* A *path* is a way of naming an item such as a struct, function, or module.
|
||||
|
||||
This chapter will cover all of these concepts. You'll be bringing names into
|
||||
This chapter will cover all of these concepts. You’ll be bringing names into
|
||||
scopes, defining scopes, and exporting names to scopes like a pro soon!
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
## Packages and Crates for Making Libraries and Executables
|
||||
|
||||
Let's talk about *packages* and *crates*. Here's a summary:
|
||||
Let’s talk about *packages* and *crates*. Here’s a summary:
|
||||
|
||||
* A *crate* is a binary or library.
|
||||
* The *crate root* is a source file that is used to know how to build a crate.
|
||||
* A *package* has a *Cargo.toml* that describes how to build one or more crates.
|
||||
At most one crate in a package can be a library.
|
||||
|
||||
So when we type `cargo new`, we're creating a package:
|
||||
So when we type `cargo new`, we’re creating a package:
|
||||
|
||||
```text
|
||||
$ cargo new my-project
|
||||
|
@ -20,18 +20,18 @@ main.rs
|
|||
```
|
||||
|
||||
Because Cargo created a *Cargo.toml*, that means we now have a package. If we
|
||||
look at the contents of *Cargo.toml*, there's no mention of *src/main.rs*.
|
||||
However, Cargo's conventions are that if you have a *src* directory containing
|
||||
*main.rs* in the same directory as a package's *Cargo.toml*, Cargo knows this
|
||||
look at the contents of *Cargo.toml*, there’s no mention of *src/main.rs*.
|
||||
However, Cargo’s conventions are that if you have a *src* directory containing
|
||||
*main.rs* in the same directory as a package’s *Cargo.toml*, Cargo knows this
|
||||
package contains a binary crate with the same name as the package, and
|
||||
*src/main.rs* is its crate root. Another convention of Cargo's is that if the
|
||||
*src/main.rs* is its crate root. Another convention of Cargo’s is that if the
|
||||
package directory contains *src/lib.rs*, the package contains a library crate
|
||||
with the same name as the package, and *src/lib.rs* is its crate root. The
|
||||
crate root files are passed by Cargo to `rustc` to actually build the library
|
||||
or binary.
|
||||
|
||||
A package can contain zero or one library crates and as many binary crates as
|
||||
you'd like. There must be at least one crate (either a library or a binary) in
|
||||
you’d like. There must be at least one crate (either a library or a binary) in
|
||||
a package.
|
||||
|
||||
If a package contains both *src/main.rs* and *src/lib.rs*, then it has two
|
||||
|
@ -40,4 +40,4 @@ the two, the package would have either a single library or binary crate. A
|
|||
package can have multiple binary crates by placing files in the *src/bin*
|
||||
directory: each file will be a separate binary crate.
|
||||
|
||||
Next, let's talk about modules!
|
||||
Next, let’s talk about modules!
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## The Module System to Control Scope and Privacy
|
||||
|
||||
Rust has a feature that's often referred to as "the module system," but it
|
||||
encompasses a few more features than modules. In this section, we'll talk about:
|
||||
Rust has a feature that’s often referred to as “the module system,” but it
|
||||
encompasses a few more features than modules. In this section, we’ll talk about:
|
||||
|
||||
* Modules, a way to organize code and control the privacy of paths
|
||||
* Paths, a way to name items
|
||||
|
@ -34,7 +34,7 @@ fn main() {
|
|||
<span class="caption">Listing 7-1: A `sound` module containing a `guitar`
|
||||
function and a `main` function</span>
|
||||
|
||||
We've defined two functions, `guitar` and `main`. We've defined the `guitar`
|
||||
We’ve defined two functions, `guitar` and `main`. We’ve defined the `guitar`
|
||||
function within a `mod` block. This block defines a module named `sound`.
|
||||
|
||||
To organize code into a hierarchy of modules, you can nest modules inside of
|
||||
|
@ -69,10 +69,10 @@ Listing 7-1. We then defined two modules within the `sound` module named
|
|||
`instrument` and `voice`. The `instrument` module has another module defined
|
||||
within it, `woodwind`, and that module contains a function named `clarinet`.
|
||||
|
||||
We mentioned in the "Packages and Crates for Making Libraries and Executables"
|
||||
We mentioned in the “Packages and Crates for Making Libraries and Executables”
|
||||
section that *src/main.rs* and *src/lib.rs* are called *crate roots*. They are
|
||||
called crate roots because the contents of either of these two files form a
|
||||
module named `crate` at the root of the crate's module tree. So in Listing 7-2,
|
||||
module named `crate` at the root of the crate’s module tree. So in Listing 7-2,
|
||||
we have a module tree that looks like Listing 7-3:
|
||||
|
||||
```text
|
||||
|
@ -94,15 +94,15 @@ entire module tree is rooted under the implicit module named `crate`.
|
|||
This tree might remind you of the directory tree of the filesystem you have on
|
||||
your computer; this is a very apt comparison! Just like directories in a
|
||||
filesystem, you place code inside whichever module will create the organization
|
||||
you'd like. Another similarity is that to refer to an item in a filesystem or a
|
||||
you’d like. Another similarity is that to refer to an item in a filesystem or a
|
||||
module tree, you use its *path*.
|
||||
|
||||
### Paths for Referring to an Item in the Module Tree
|
||||
|
||||
If we want to call a function, we need to know its *path*. "Path" is a synonym
|
||||
for "name" in a way, but it evokes that filesystem metaphor. Additionally,
|
||||
If we want to call a function, we need to know its *path*. “Path” is a synonym
|
||||
for “name” in a way, but it evokes that filesystem metaphor. Additionally,
|
||||
functions, structs, and other items may have multiple paths that refer to the
|
||||
same item, so "name" isn't quite the right concept.
|
||||
same item, so “name” isn’t quite the right concept.
|
||||
|
||||
A *path* can take two forms:
|
||||
|
||||
|
@ -115,10 +115,10 @@ Both absolute and relative paths are followed by one or more identifiers
|
|||
separated by double colons (`::`).
|
||||
|
||||
How do we call the `clarinet` function in the `main` function in Listing 7-2?
|
||||
That is, what's the path of the `clarinet` function? In Listing 7-4, let's
|
||||
simplify our code a bit by removing some of the modules, and we'll show two
|
||||
ways to call the `clarinet` function from `main`. This example won't compile
|
||||
just yet, we'll explain why in a bit.
|
||||
That is, what’s the path of the `clarinet` function? In Listing 7-4, let’s
|
||||
simplify our code a bit by removing some of the modules, and we’ll show two
|
||||
ways to call the `clarinet` function from `main`. This example won’t compile
|
||||
just yet, we’ll explain why in a bit.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -144,7 +144,7 @@ fn main() {
|
|||
simplified module tree from the `main` function using absolute and relative
|
||||
paths</span>
|
||||
|
||||
The first way we're calling the `clarinet` function from the `main` function
|
||||
The first way we’re calling the `clarinet` function from the `main` function
|
||||
uses an absolute path. Because `clarinet` is defined within the same crate as
|
||||
`main`, we use the `crate` keyword to start an absolute path. Then we include
|
||||
each of the modules until we make our way to `clarinet`. This is similar to
|
||||
|
@ -152,13 +152,13 @@ specifying the path `/sound/instrument/clarinet` to run the program at that
|
|||
location on your computer; using the `crate` name to start from the crate root
|
||||
is like using `/` to start from the filesystem root in your shell.
|
||||
|
||||
The second way we're calling the `clarinet` function from the `main` function
|
||||
The second way we’re calling the `clarinet` function from the `main` function
|
||||
uses a relative path. The path starts with the name `sound`, a module defined
|
||||
at the same level of the module tree as the `main` function. This is similar to
|
||||
specifying the path `sound/instrument/clarinet` to run the program at that
|
||||
location on your computer; starting with a name means that the path is relative.
|
||||
|
||||
We mentioned that Listing 7-4 won't compile yet, let's try to compile it and
|
||||
We mentioned that Listing 7-4 won’t compile yet, let’s try to compile it and
|
||||
find out why not! The error we get is shown in Listing 7-5.
|
||||
|
||||
```text
|
||||
|
@ -182,37 +182,37 @@ Listing 7-4</span>
|
|||
|
||||
The error messsages say that module `instrument` is private. We can see that we
|
||||
have the correct paths for the `instrument` module and the `clarinet` function,
|
||||
but Rust won't let us use them because they're private. It's time to learn
|
||||
but Rust won’t let us use them because they’re private. It’s time to learn
|
||||
about the `pub` keyword!
|
||||
|
||||
### Modules as the Privacy Boundary
|
||||
|
||||
Earlier, we talked about the syntax of modules and that they can be used for
|
||||
organization. There's another reason Rust has modules: modules are the *privacy
|
||||
organization. There’s another reason Rust has modules: modules are the *privacy
|
||||
boundary* in Rust. If you want to make an item like a function or struct
|
||||
private, you put it in a module. Here are the privacy rules:
|
||||
|
||||
* All items (functions, methods, structs, enums, modules, annd constants) are
|
||||
private by default.
|
||||
* You can use the `pub` keyword to make an item public.
|
||||
* You aren't allowed to use private code defined in modules that are children
|
||||
* You aren’t allowed to use private code defined in modules that are children
|
||||
of the current module.
|
||||
* You are allowed to use any code defined in ancestor modules or the current
|
||||
module.
|
||||
|
||||
In other words, items without the `pub` keyword are private as you look "down"
|
||||
In other words, items without the `pub` keyword are private as you look “down”
|
||||
the module tree from the current module, but items without the `pub` keyword
|
||||
are public as you look "up" the tree from the current module. Again, think of a
|
||||
filesystem: if you don't have permissions to a directory, you can't look into
|
||||
are public as you look “up” the tree from the current module. Again, think of a
|
||||
filesystem: if you don’t have permissions to a directory, you can’t look into
|
||||
it from its parent directory. If you do have permissions to a directory, you
|
||||
can look inside it and any of its ancestor directories.
|
||||
|
||||
### Using the `pub` Keyword to Make Items Public
|
||||
|
||||
The error in Listing 7-5 said the `instrument` module is private. Let's mark
|
||||
The error in Listing 7-5 said the `instrument` module is private. Let’s mark
|
||||
the `instrument` module with the `pub` keyword so that we can use it from the
|
||||
`main` function. This change is shown in Listing 7-6, which still won't
|
||||
compile, but we'll get a different error:
|
||||
`main` function. This change is shown in Listing 7-6, which still won’t
|
||||
compile, but we’ll get a different error:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -235,10 +235,10 @@ fn main() {
|
|||
```
|
||||
|
||||
<span class="caption">Listing 7-6: Declaring the `instrument` module as `pub`
|
||||
so that we're allowed to use it from `main`</span>
|
||||
so that we’re allowed to use it from `main`</span>
|
||||
|
||||
Adding the `pub` keyword in front of `mod instrument` makes the module public.
|
||||
With this change, if we're allowed to access `sound`, we can access
|
||||
With this change, if we’re allowed to access `sound`, we can access
|
||||
`instrument`. The contents of `instrument` are still private; making the module
|
||||
public does not make its contents public. The `pub` keyword on a module lets
|
||||
code in its parent module refer to it.
|
||||
|
@ -268,7 +268,7 @@ Listing 7-6</span>
|
|||
The errors now say that the `clarinet` function is private. The privacy rules
|
||||
apply to structs, enums, functions, and methods as well as modules.
|
||||
|
||||
Let's make the `clarinet` function public as well by adding the `pub` keyword
|
||||
Let’s make the `clarinet` function public as well by adding the `pub` keyword
|
||||
before its definition, as shown in Listing 7-8:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
@ -294,15 +294,15 @@ fn main() {
|
|||
<span class="caption">Listing 7-8: Adding the `pub` keyword to both `mod
|
||||
instrument` and `fn clarinet` lets us call the function from `main`</span>
|
||||
|
||||
This will now compile! Let's look at both the absolute and the relative path
|
||||
This will now compile! Let’s look at both the absolute and the relative path
|
||||
and double check why adding the `pub` keyword lets us use these paths in `main`.
|
||||
|
||||
In the absolute path case, we start with `crate`, the root of our crate. From
|
||||
there, we have `sound`, and it is a module that is defined in the crate root.
|
||||
The `sound` module isn't public, but because the `main` function is defined in
|
||||
the same module that `sound` is defined, we're allowed to refer to `sound` from
|
||||
The `sound` module isn’t public, but because the `main` function is defined in
|
||||
the same module that `sound` is defined, we’re allowed to refer to `sound` from
|
||||
`main`. Next is `instrument`, which is a module marked with `pub`. We can
|
||||
access the parent module of `instrument`, so we're allowed to access
|
||||
access the parent module of `instrument`, so we’re allowed to access
|
||||
`instrument`. Finally, `clarinet` is a function marked with `pub` and we can
|
||||
access its parent module, so this function call works!
|
||||
|
||||
|
@ -369,7 +369,7 @@ mod sound {
|
|||
```
|
||||
|
||||
<span class="caption">Listing 7-10: Adding a parent module named `sound`
|
||||
doesn't affect the relative path `super::breathe_in`</span>
|
||||
doesn’t affect the relative path `super::breathe_in`</span>
|
||||
|
||||
The call to `super::breathe_in` from the `clarinet` function will continue to
|
||||
work in Listing 7-10 as it did in Listing 7-9, without needing to update the
|
||||
|
@ -381,12 +381,12 @@ rearranging modules.
|
|||
|
||||
### Using `pub` with Structs and Enums
|
||||
|
||||
You can designate structs and enums to be public in a similar way as we've
|
||||
You can designate structs and enums to be public in a similar way as we’ve
|
||||
shown with modules and functions, with a few additional details.
|
||||
|
||||
If you use `pub` before a struct definition, you make the struct public.
|
||||
However, the struct's fields are still private. You can choose to make each
|
||||
field public or not on a case-by-case basis. In Listing 7-11, we've defined a
|
||||
However, the struct’s fields are still private. You can choose to make each
|
||||
field public or not on a case-by-case basis. In Listing 7-11, we’ve defined a
|
||||
public `plant::Vegetable` struct with a public `name` field but a private `id`
|
||||
field.
|
||||
|
||||
|
@ -424,14 +424,14 @@ fn main() {
|
|||
private fields</span>
|
||||
|
||||
Because the `name` field of the `plant::Vegetable` struct is public, in `main`
|
||||
we can write and read to the `name` field by using dot notation. We're not
|
||||
allowed to use the `id` field in `main` because it's private. Try uncommenting
|
||||
we can write and read to the `name` field by using dot notation. We’re not
|
||||
allowed to use the `id` field in `main` because it’s private. Try uncommenting
|
||||
the line printing the `id` field value to see what error you get! Also note
|
||||
that because `plant::Vegetable` has a private field, the struct needs to
|
||||
provide a public associated function that constructs an instance of `Vegetable`
|
||||
(we've used the conventional name `new` here). If `Vegetable` didn't have such
|
||||
a function, we wouldn't be able to create an instance of `Vegetable` in `main`
|
||||
because we're not allowed to set the value of the private `id` field in `main`.
|
||||
(we’ve used the conventional name `new` here). If `Vegetable` didn’t have such
|
||||
a function, we wouldn’t be able to create an instance of `Vegetable` in `main`
|
||||
because we’re not allowed to set the value of the private `id` field in `main`.
|
||||
|
||||
In contrast, if you make a public enum, all of its variants are public. You
|
||||
only need the `pub` before the `enum` keyword, as shown in Listing 7-12.
|
||||
|
@ -455,21 +455,21 @@ fn main() {
|
|||
<span class="caption">Listing 7-12: Designating an enum as public makes all its
|
||||
variants public</span>
|
||||
|
||||
Because we made the `Appetizer` enum public, we're able to use the `Soup` and
|
||||
Because we made the `Appetizer` enum public, we’re able to use the `Soup` and
|
||||
`Salad` variants in `main`.
|
||||
|
||||
There's one more situation involving `pub` that we haven't covered, and that's
|
||||
with our last module system feature: the `use` keyword. Let's cover `use` by
|
||||
itself, and then we'll show how `pub` and `use` can be combined.
|
||||
There’s one more situation involving `pub` that we haven’t covered, and that’s
|
||||
with our last module system feature: the `use` keyword. Let’s cover `use` by
|
||||
itself, and then we’ll show how `pub` and `use` can be combined.
|
||||
|
||||
### The `use` Keyword to Bring Paths into a Scope
|
||||
|
||||
You may have been thinking that many of the paths we've written to call
|
||||
You may have been thinking that many of the paths we’ve written to call
|
||||
functions in the listings in this chapter are long and repetitive. For example,
|
||||
in Listing 7-8, whether we chose the absolute or relative path to the
|
||||
`clarinet` function, every time we wanted to call `clarinet` we had to specify
|
||||
`sound` and `instrument` too. Luckily, there's a way to bring a path into a
|
||||
scope once and then call the items in that path as if they're local items: with
|
||||
`sound` and `instrument` too. Luckily, there’s a way to bring a path into a
|
||||
scope once and then call the items in that path as if they’re local items: with
|
||||
the `use` keyword. In Listing 7-13, we bring the `crate::sound::instrument`
|
||||
module into the scope of the `main` function so that we only have to specify
|
||||
`instrument::clarinet` to call the `clarinet` function in `main`.
|
||||
|
@ -503,10 +503,10 @@ the filesystem. By adding `use crate::sound::instrument` in the crate root,
|
|||
`instrument` is now a valid name in that scope as if the `instrument` module
|
||||
had been defined in the crate root. We can now reach items in the `instrument`
|
||||
module through the older, full paths, or we can reach items through the new,
|
||||
shorter path that we've created with `use`. Paths brought into scope with `use`
|
||||
shorter path that we’ve created with `use`. Paths brought into scope with `use`
|
||||
also check privacy, like any other paths.
|
||||
|
||||
If you want to bring an item into scope with `use` and a relative path, there's
|
||||
If you want to bring an item into scope with `use` and a relative path, there’s
|
||||
a small difference from directly calling the item using a relative path:
|
||||
instead of starting from a name in the current scope, you must start the path
|
||||
given to `use` with `self`. Listing 7-14 shows how to specify a relative path
|
||||
|
@ -536,7 +536,7 @@ fn main() {
|
|||
a relative path starting with `self`</span>
|
||||
|
||||
Starting relative paths with `self` when specified after `use` might not be
|
||||
neccesary in the future; it's an inconsistency in the language that people are
|
||||
neccesary in the future; it’s an inconsistency in the language that people are
|
||||
working on eliminating.
|
||||
|
||||
Choosing to specify absolute paths with `use` can make updates easier if the
|
||||
|
@ -545,7 +545,7 @@ code defining the items does not, as opposed to when they moved together in the
|
|||
changes we made in Listing 7-10. For example, if we decide to take the code
|
||||
from Listing 7-13, extract the behavior in the `main` function to a function
|
||||
called `clarinet_trio`, and move that function into a module named
|
||||
`performance_group`, the path specified in `use` wouldn't need to change, as
|
||||
`performance_group`, the path specified in `use` wouldn’t need to change, as
|
||||
shown in Listing 7-15.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
@ -574,14 +574,14 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
<span class="caption">Listing 7-15: The absolute path doesn't need to be
|
||||
<span class="caption">Listing 7-15: The absolute path doesn’t need to be
|
||||
updated when moving the code that calls the item</span>
|
||||
|
||||
In contrast, if we made the same change to the code in Listing 7-14 that
|
||||
specifies a relative path, we would need to change `use
|
||||
self::sound::instrument` to `use super::sound::instrument`. Choosing whether
|
||||
relative or absolute paths will result in fewer updates can be a guess if
|
||||
you're not sure how your module tree will change in the future, but your
|
||||
you’re not sure how your module tree will change in the future, but your
|
||||
authors tend to specify absolute paths starting with `crate` because code
|
||||
defining and calling items is more likely to be moved around the module tree
|
||||
independently of each other, rather than together as we saw in Listing 7-10.
|
||||
|
@ -615,15 +615,15 @@ fn main() {
|
|||
<span class="caption">Listing 7-16: Bringing the `clarinet` function into
|
||||
scoope with `use`, which is unidiomatic</span>
|
||||
|
||||
For functions, it's considered idiomatic to specify the function's parent
|
||||
For functions, it’s considered idiomatic to specify the function’s parent
|
||||
module with `use`, and then specify the parent module when calling the
|
||||
function. Doing so rather than specifying the path to the function with `use`,
|
||||
as Listing 7-16 does, makes it clear that the function isn't locally defined,
|
||||
as Listing 7-16 does, makes it clear that the function isn’t locally defined,
|
||||
while still minimizing repetition of the full path.
|
||||
|
||||
For structs, enums, and other items, specifying the full path to the item with
|
||||
`use` is idiomatic. For example, Listing 7-17 shows the idiomatic way to bring
|
||||
the standard library's `HashMap` struct into scope.
|
||||
the standard library’s `HashMap` struct into scope.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -640,7 +640,7 @@ fn main() {
|
|||
idiomatic way</span>
|
||||
|
||||
In contrast, the code in Listing 7-18 that brings the parent module of
|
||||
`HashMap` into scope would not be considered idiomatic. There's not a strong
|
||||
`HashMap` into scope would not be considered idiomatic. There’s not a strong
|
||||
reason for this idiom; this is the convention that has emerged and folks have
|
||||
gotten used to reading and writing.
|
||||
|
||||
|
@ -659,7 +659,7 @@ fn main() {
|
|||
unidiomatic way</span>
|
||||
|
||||
The exception to this idiom is if the `use` statements would bring two items
|
||||
with the same name into scope, which isn't allowed. Listing 7-19 shows how to
|
||||
with the same name into scope, which isn’t allowed. Listing 7-19 shows how to
|
||||
bring two `Result` types that have different parent modules into scope and
|
||||
refer to them.
|
||||
|
||||
|
@ -680,13 +680,13 @@ fn function2() -> io::Result<()> {
|
|||
<span class="caption">Listing 7-19: Bringing two types with the same name into
|
||||
the same scope requires using their parent modules</span>
|
||||
|
||||
If instead we specified `use std::fmt::Result` and `use std::io::Result`, we'd
|
||||
have two `Result` types in the same scope and Rust wouldn't know which one we
|
||||
If instead we specified `use std::fmt::Result` and `use std::io::Result`, we’d
|
||||
have two `Result` types in the same scope and Rust wouldn’t know which one we
|
||||
meant when we used `Result`. Try it and see what compiler error you get!
|
||||
|
||||
### Renaming Types Brought Into Scope with the `as` Keyword
|
||||
|
||||
There's another solution to the problem of bringing two types of the same name
|
||||
There’s another solution to the problem of bringing two types of the same name
|
||||
into the same scope: we can specify a new local name for the type by adding
|
||||
`as` and a new name after the `use`. Listing 7-20 shows another way to write
|
||||
the code from Listing 7-19 by renaming one of the two `Result` types using `as`.
|
||||
|
@ -705,12 +705,12 @@ fn function2() -> IoResult<()> {
|
|||
}
|
||||
```
|
||||
|
||||
<span class="caption">Listing 7-20: Renaming a type when it's brought into
|
||||
<span class="caption">Listing 7-20: Renaming a type when it’s brought into
|
||||
scope with the `as` keyword</span>
|
||||
|
||||
In the second `use` statement, we chose the new name `IoResult` for the
|
||||
`std::io::Result` type, which won't conflict with the `Result` from `std::fmt`
|
||||
that we've also brought into scope. This is also considered idiomatic; choosing
|
||||
`std::io::Result` type, which won’t conflict with the `Result` from `std::fmt`
|
||||
that we’ve also brought into scope. This is also considered idiomatic; choosing
|
||||
between the code in Listing 7-19 and Listing 7-20 is up to you.
|
||||
|
||||
### Re-exporting Names with `pub use`
|
||||
|
@ -719,7 +719,7 @@ When you bring a name into scope with the `use` keyword, the name being
|
|||
available in the new scope is private. If you want to enable code calling your
|
||||
code to be able to refer to the type as if it was defined in that scope just as
|
||||
your code does, you can combine `pub` and `use`. This technique is called
|
||||
*re-exporting* because you're bringing an item into scope but also making that
|
||||
*re-exporting* because you’re bringing an item into scope but also making that
|
||||
item available for others to bring into their scope.
|
||||
|
||||
For example, Listing 7-21 shows the code from Listing 7-15 with the `use`
|
||||
|
@ -757,8 +757,8 @@ from a new scope with `pub use`</span>
|
|||
|
||||
By using `pub use`, the `main` function can now call the `clarinet` function
|
||||
through this new path with `performance_group::instrument::clarinet`. If we
|
||||
hadn't specified `pub use`, the `clarinet_trio` function can call
|
||||
`instrument::clarinet` in its scope but `main` wouldn't be allowed to take
|
||||
hadn’t specified `pub use`, the `clarinet_trio` function can call
|
||||
`instrument::clarinet` in its scope but `main` wouldn’t be allowed to take
|
||||
advantage of this new path.
|
||||
|
||||
### Using External Packages
|
||||
|
@ -780,7 +780,7 @@ available to our project.
|
|||
|
||||
Then, to bring `rand` definitions into the scope of our package, we added a
|
||||
`use` line starting with the name of the package, `rand`, and listing the items
|
||||
we wanted to bring into scope. Recall that in the "Generating a Random Number"
|
||||
we wanted to bring into scope. Recall that in the “Generating a Random Number”
|
||||
section in Chapter 2, we brought the `Rng` trait into scope and called the
|
||||
`rand::thread_rng` function:
|
||||
|
||||
|
@ -794,13 +794,13 @@ fn main() {
|
|||
|
||||
There are many packages that members of the community have published on
|
||||
*https://crates.io*, and pulling any of them in to your package involves these
|
||||
same steps: listing them in your package's *Cargo.toml* and bringing items
|
||||
same steps: listing them in your package’s *Cargo.toml* and bringing items
|
||||
defined in them into a scope in your package with `use`.
|
||||
|
||||
Note that the standard library (`std`) is also a crate that's external to your
|
||||
Note that the standard library (`std`) is also a crate that’s external to your
|
||||
package. Because the standard library is shipped with the Rust language, you
|
||||
don't need to change *Cargo.toml* to include `std`, but you refer to it in
|
||||
`use` to bring items the standard library defines into your package's scope,
|
||||
don’t need to change *Cargo.toml* to include `std`, but you refer to it in
|
||||
`use` to bring items the standard library defines into your package’s scope,
|
||||
such as with `HashMap`:
|
||||
|
||||
```rust
|
||||
|
@ -858,7 +858,7 @@ use std::io::Write;
|
|||
<span class="caption">Listing 7-23: Bringing two paths into scope in two `use`
|
||||
statements where one is a sub-path of the other</span>
|
||||
|
||||
The common part between these two paths is `std::io`, and that's the complete
|
||||
The common part between these two paths is `std::io`, and that’s the complete
|
||||
first path. To deduplicate these two paths into one `use` statement, we can use
|
||||
`self` in the nested path as shown in Listing 7-24.
|
||||
|
||||
|
@ -875,7 +875,7 @@ This brings both `std::io` and `std::io::Write` into scope.
|
|||
|
||||
### Bringing All Public Definitions into Scope with the Glob Operator
|
||||
|
||||
If you'd like to bring *all* public items defined in a path into scope, you can
|
||||
If you’d like to bring *all* public items defined in a path into scope, you can
|
||||
use specify that path followed by `*`, the glob operator:
|
||||
|
||||
```rust
|
||||
|
@ -889,7 +889,7 @@ Be careful with using the glob operator! It makes it harder to tell what names
|
|||
are in scope and where a name your program uses was defined.
|
||||
|
||||
The glob operator is often used when testing to bring everything under test
|
||||
into the `tests` module; we'll talk about that in the "How to Write Tests"
|
||||
into the `tests` module; we’ll talk about that in the “How to Write Tests”
|
||||
section of Chapter 11. The glob operator is also sometimes used as part of the
|
||||
prelude pattern; see [the standard library
|
||||
documentation](../../std/prelude/index.html#other-preludes) for more
|
||||
|
@ -972,7 +972,7 @@ Rust provides ways to organize your packages into crates, your crates into
|
|||
modules, and to refer to items defined in one module from another by specifying
|
||||
absolute or relative paths. These paths can be brought into a scope with a
|
||||
`use` statement so that you can use a shorter path for multiple uses of the
|
||||
item in that scope. Modules define code that's private by default, but you can
|
||||
item in that scope. Modules define code that’s private by default, but you can
|
||||
choose to make definitions public by adding the `pub` keyword.
|
||||
|
||||
Next, we’ll look at some collection data structures in the standard library
|
||||
|
|
|
@ -243,7 +243,7 @@ elements in a vector</span>
|
|||
|
||||
To change the value that the mutable reference refers to, we have to use the
|
||||
dereference operator (`*`) to get to the value in `i` before we can use the
|
||||
`+=` operator . We'll talk more about `*` in Chapter 15.
|
||||
`+=` operator . We’ll talk more about `*` in Chapter 15.
|
||||
|
||||
### Using an Enum to Store Multiple Types
|
||||
|
||||
|
|
|
@ -261,7 +261,7 @@ loop, so all of these changes are safe and allowed by the borrowing rules.
|
|||
|
||||
### Hashing Functions
|
||||
|
||||
By default, `HashMap` uses a "cryptographically strong"[^siphash] hashing function that can
|
||||
By default, `HashMap` uses a “cryptographically strong”[^siphash] hashing function that can
|
||||
provide resistance to Denial of Service (DoS) attacks. This is not the fastest
|
||||
hashing algorithm available, but the trade-off for better security that comes
|
||||
with the drop in performance is worth it. If you profile your code and find
|
||||
|
|
|
@ -189,8 +189,8 @@ the file can’t be opened, a different error message will be printed. The last
|
|||
arm of the outer `match` stays the same so the program panics on any error
|
||||
besides the missing file error.
|
||||
|
||||
That's a lot of `match`! `match` is very powerful, but also very much a primitive.
|
||||
In Chapter 13, we'll learn about closures. The `Result<T, E>` type has many
|
||||
That’s a lot of `match`! `match` is very powerful, but also very much a primitive.
|
||||
In Chapter 13, we’ll learn about closures. The `Result<T, E>` type has many
|
||||
methods that accept a closure, and are implemented as `match` statements. A more
|
||||
seasoned Rustacean might write this:
|
||||
|
||||
|
@ -211,10 +211,10 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
Come back to this example after you've read Chapter 13, and look up what the
|
||||
Come back to this example after you’ve read Chapter 13, and look up what the
|
||||
`map_err` and `unwrap_or_else` methods do in the standard library
|
||||
documentation. There's many more of these methods that can clean up huge
|
||||
nested `match`es when dealing with errors. We'll be looking at some other
|
||||
documentation. There’s many more of these methods that can clean up huge
|
||||
nested `match`es when dealing with errors. We’ll be looking at some other
|
||||
strategies shortly!
|
||||
|
||||
### Shortcuts for Panic on Error: `unwrap` and `expect`
|
||||
|
@ -317,9 +317,9 @@ fn read_username_from_file() -> Result<String, io::Error> {
|
|||
<span class="caption">Listing 9-6: A function that returns errors to the
|
||||
calling code using `match`</span>
|
||||
|
||||
This function can be written in a much shorter way, but we're going to start by
|
||||
This function can be written in a much shorter way, but we’re going to start by
|
||||
doing a lot of it manually in order to explore error handling; at the end,
|
||||
we'll show the easy way. Let’s look at the return type of the function first:
|
||||
we’ll show the easy way. Let’s look at the return type of the function first:
|
||||
`Result<String, io::Error>`. This means the function is returning a value of
|
||||
the type `Result<T, E>` where the generic parameter `T` has been filled in
|
||||
with the concrete type `String`, and the generic type `E` has been filled in
|
||||
|
@ -444,7 +444,7 @@ username in `s` when both `File::open` and `read_to_string` succeed rather than
|
|||
returning errors. The functionality is again the same as in Listing 9-6 and
|
||||
Listing 9-7; this is just a different, more ergonomic way to write it.
|
||||
|
||||
Speaking of different ways to write this function, there's a way to make this even
|
||||
Speaking of different ways to write this function, there’s a way to make this even
|
||||
shorter:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
@ -464,7 +464,7 @@ Reading a file into a string is a fairly common operation, and so Rust
|
|||
provides a convenience function called `fs::read_to_string` that will
|
||||
open the file, create a new `String`, read the contents of the file,
|
||||
and put the contents into that `String`, and then return it. Of course,
|
||||
this doesn't give us the opportunity to show off all of this error handling,
|
||||
this doesn’t give us the opportunity to show off all of this error handling,
|
||||
so we did it the hard way at first.
|
||||
|
||||
#### The `?` Operator Can Only Be Used in Functions That Return `Result`
|
||||
|
@ -518,8 +518,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
```
|
||||
|
||||
The `Box<dyn Error>` is called a "trait object", which we'll talk about in Chapter 17.
|
||||
For now, you can read `Box<dyn Error>` to mean "any kind of error."
|
||||
The `Box<dyn Error>` is called a “trait object”, which we’ll talk about in Chapter 17.
|
||||
For now, you can read `Box<dyn Error>` to mean “any kind of error.”
|
||||
|
||||
Now that we’ve discussed the details of calling `panic!` or returning `Result`,
|
||||
let’s return to the topic of how to decide which is appropriate to use in which
|
||||
|
|
|
@ -266,7 +266,7 @@ can explore how to use traits to accept arguments of many different types.
|
|||
For example, in Listing 10-13, we implemented the `Summary` trait on the types
|
||||
`NewsArticle` and `Tweet`. We can define a function `notify` that calls the
|
||||
`summarize` method on its parameter `item`, which is of some type that implements
|
||||
the `Summary` trait. To do this, we can use the '`impl Trait`' syntax, like this:
|
||||
the `Summary` trait. To do this, we can use the ‘`impl Trait`’ syntax, like this:
|
||||
|
||||
```rust,ignore
|
||||
pub fn notify(item: impl Summary) {
|
||||
|
@ -280,7 +280,7 @@ the `Summary` trait, like `summarize`.
|
|||
#### Trait Bounds
|
||||
|
||||
The `impl Trait` syntax works for short examples, but is syntax sugar for a
|
||||
longer form. This is called a 'trait bound', and it looks like this:
|
||||
longer form. This is called a ‘trait bound’, and it looks like this:
|
||||
|
||||
```rust,ignore
|
||||
pub fn notify<T: Summary>(item: T) {
|
||||
|
@ -313,15 +313,17 @@ pub fn notify<T: Summary>(item1: T, item2: T) {
|
|||
|
||||
#### Specify multiple traits with `+`
|
||||
|
||||
If `notify` needed to display formatting on `item`, as well as use the `summarize`
|
||||
method, then `item` would need to implement two different traits at the same time:
|
||||
`Display` and `Summary`. This can be done using the `+` syntax:
|
||||
If `notify` needed to display formatting on `item`, as well as use the
|
||||
`summarize` method, then `item` would need to implement two different traits at
|
||||
the same time: `Display` and `Summary`. This can be done using the `+` syntax:
|
||||
|
||||
```rust,ignore
|
||||
pub fn notify(item: impl Summary + Display) {
|
||||
```
|
||||
This syntax is also valid with trait bounds on generic types:
|
||||
```rust,ignore
|
||||
|
||||
This syntax is also valid with trait bounds on generic types:
|
||||
|
||||
```rust,ignore
|
||||
pub fn notify<T: Summary + Display>(item: T) {
|
||||
```
|
||||
|
||||
|
@ -367,17 +369,17 @@ fn returns_summarizable() -> impl Summary {
|
|||
}
|
||||
```
|
||||
|
||||
This signature says, "I'm going to return something that implements the
|
||||
`Summary` trait, but I'm not going to tell you the exact type." In our case,
|
||||
we're returning a `Tweet`, but the caller doesn't know that.
|
||||
This signature says, “I’m going to return something that implements the
|
||||
`Summary` trait, but I’m not going to tell you the exact type.” In our case,
|
||||
we’re returning a `Tweet`, but the caller doesn’t know that.
|
||||
|
||||
Why is this useful? In chapter 13, we're going to learn about two features
|
||||
Why is this useful? In chapter 13, we’re going to learn about two features
|
||||
that rely heavily on traits: closures, and iterators. These features create
|
||||
types that only the compiler knows, or types that are very, very long.
|
||||
`impl Trait` lets you simply say "this returns an `Iterator`" without
|
||||
`impl Trait` lets you simply say “this returns an `Iterator`” without
|
||||
needing to write out a really long type.
|
||||
|
||||
This only works if you have a single type that you're returning, however.
|
||||
This only works if you have a single type that you’re returning, however.
|
||||
For example, this would *not* work:
|
||||
|
||||
```rust,ignore,does_not_compile
|
||||
|
@ -402,8 +404,8 @@ fn returns_summarizable(switch: bool) -> impl Summary {
|
|||
```
|
||||
|
||||
Here, we try to return either a `NewsArticle` or a `Tweet`. This cannot work,
|
||||
due to restrictions around how `impl Trait` works. To write this code, you'll
|
||||
have to wait until Chapter 17, "trait objects".
|
||||
due to restrictions around how `impl Trait` works. To write this code, you’ll
|
||||
have to wait until Chapter 17, “trait objects”.
|
||||
|
||||
### Fixing the `largest` Function with Trait Bounds
|
||||
|
||||
|
|
|
@ -802,8 +802,8 @@ figuring out where our bug is!
|
|||
|
||||
### Using `Result<T, E>` in tests
|
||||
|
||||
So far, we've written tests that panic when they fail. We can also write tests
|
||||
that use `Result<T, E>` too! Here's that first example, but with results instead:
|
||||
So far, we’ve written tests that panic when they fail. We can also write tests
|
||||
that use `Result<T, E>` too! Here’s that first example, but with results instead:
|
||||
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
|
@ -819,11 +819,11 @@ mod tests {
|
|||
}
|
||||
```
|
||||
|
||||
Here, we've changed the `it_works` function to return a result. And in the body,
|
||||
Here, we’ve changed the `it_works` function to return a result. And in the body,
|
||||
rather than `assert_eq!`, we return `Ok(())` for the success case, and an `Err`
|
||||
with a `String` inside for the failure case. As before, this test will fail or
|
||||
succeed, but instead of being based on panics, it will use the `Result<T, E>` to
|
||||
make that determination. Because of this, you can't use `#[should_panic]` with one
|
||||
make that determination. Because of this, you can’t use `#[should_panic]` with one
|
||||
of these functions; you should have it be returning an `Err` instead!
|
||||
|
||||
Now that you know several ways to write tests, let’s look at what is happening
|
||||
|
|
|
@ -92,7 +92,7 @@ mod tests {
|
|||
|
||||
Note that the `internal_adder` function is not marked as `pub`, but because
|
||||
tests are just Rust code and the `tests` module is just another module, you can
|
||||
bring `internal_adder` into a test's scope and call it. If you don’t think
|
||||
bring `internal_adder` into a test’s scope and call it. If you don’t think
|
||||
private functions should be tested, there’s nothing in Rust that will compel
|
||||
you to do so.
|
||||
|
||||
|
@ -133,7 +133,7 @@ fn it_adds_two() {
|
|||
|
||||
We’ve added `use adder` at the top of the code, which we didn’t need in the
|
||||
unit tests. The reason is that each test in the `tests` directory is a separate
|
||||
crate, so we need to bring our library into each test crate's scope.
|
||||
crate, so we need to bring our library into each test crate’s scope.
|
||||
|
||||
We don’t need to annotate any code in *tests/integration_test.rs* with
|
||||
`#[cfg(test)]`. Cargo treats the `tests` directory specially and compiles files
|
||||
|
|
|
@ -23,7 +23,7 @@ reading the file fails, but the error message just prints
|
|||
`something went wrong`. Reading a file can fail in a number of ways: for
|
||||
example, the file could be missing, or we might not have permission to open
|
||||
it. Right now, regardless of the situation, we’d print the
|
||||
`something went wrong` error message, which wouldn't give the user any
|
||||
`something went wrong` error message, which wouldn’t give the user any
|
||||
information!
|
||||
|
||||
Fourth, we use `expect` repeatedly to handle different errors, and if the user
|
||||
|
@ -524,8 +524,8 @@ We’ll cover trait objects in Chapter 17. For now, just know that `Box<dyn
|
|||
Error>` means the function will return a type that implements the `Error`
|
||||
trait, but we don’t have to specify what particular type the return value
|
||||
will be. This gives us flexibility to return error values that may be of
|
||||
different types in different error cases. This is what the `dyn` means, it's
|
||||
short for "dynamic."
|
||||
different types in different error cases. This is what the `dyn` means, it’s
|
||||
short for “dynamic.”
|
||||
|
||||
Second, we’ve removed the call to `expect` in favor of `?`, as we talked about
|
||||
in Chapter 9. Rather than `panic!` on an error, `?` will return the error value
|
||||
|
|
|
@ -41,10 +41,10 @@ opt-level = 3
|
|||
The `opt-level` setting controls the number of optimizations Rust will apply to
|
||||
your code, with a range of 0 to 3. Applying more optimizations extends
|
||||
compiling time, so if you’re in development and compiling your code often,
|
||||
you'll want faster compiling even if the resulting code runs slower. That is
|
||||
you’ll want faster compiling even if the resulting code runs slower. That is
|
||||
the reason the default `opt-level` for `dev` is `0`. When you’re ready to
|
||||
release your code, it’s best to spend more time compiling. You’ll only compile
|
||||
in release mode once, but you'll run the compiled program many times, so
|
||||
in release mode once, but you’ll run the compiled program many times, so
|
||||
release mode trades longer compile time for code that runs faster. That is why
|
||||
the default `opt-level` for the `release` profile is `3`.
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ including the comment describing the crate as a whole</span>
|
|||
|
||||
Documentation comments within items are useful for describing crates and
|
||||
modules especially. Use them to explain the overall purpose of the container to
|
||||
help your users understand the crate's organization.
|
||||
help your users understand the crate’s organization.
|
||||
|
||||
### Exporting a Convenient Public API with `pub use`
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ smart pointers to work in a similar way as references. Then we’ll look at
|
|||
Rust’s *deref coercion* feature and how it lets us work with either references
|
||||
or smart pointers.
|
||||
|
||||
> There's one big difference between the `MyBox<T>` type we're about to build
|
||||
> There’s one big difference between the `MyBox<T>` type we’re about to build
|
||||
> and the real `Box<T>`: our version will not store its data on the heap. We
|
||||
> are focusing this example on `Deref`, and so where the data is actually stored
|
||||
> is less important than the pointer-like behavior.
|
||||
|
|
|
@ -124,7 +124,7 @@ for the operating system to switch between the threads.
|
|||
### Waiting for All Threads to Finish Using `join` Handles
|
||||
|
||||
The code in Listing 16-1 not only stops the spawned thread prematurely most of
|
||||
the time due to the main thread ending, but also can't guarantee that the
|
||||
the time due to the main thread ending, but also can’t guarantee that the
|
||||
spawned thread will get to run at all. The reason is that there is no guarantee
|
||||
on the order in which threads run!
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
One increasingly popular approach to ensuring safe concurrency is *message
|
||||
passing*, where threads or actors communicate by sending each other messages
|
||||
containing data. Here’s the idea in a slogan from [the Go language
|
||||
documentation](http://golang.org/doc/effective_go.html): "Do not communicate by
|
||||
sharing memory; instead, share memory by communicating."
|
||||
documentation](http://golang.org/doc/effective_go.html): “Do not communicate by
|
||||
sharing memory; instead, share memory by communicating.”
|
||||
|
||||
One major tool Rust has for accomplishing message-sending concurrency is the
|
||||
*channel*, a programming concept that Rust’s standard library provides an
|
||||
|
@ -165,7 +165,7 @@ advantage of thinking about ownership throughout your Rust programs. Let’s do
|
|||
an experiment to show how channels and ownership work together to prevent
|
||||
problems: we’ll try to use a `val` value in the spawned thread *after* we’ve
|
||||
sent it down the channel. Try compiling the code in Listing 16-9 to see why
|
||||
this code isn't allowed:
|
||||
this code isn’t allowed:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
|
|
@ -881,7 +881,7 @@ Using `@` lets us test a value and save it in a variable within one pattern.
|
|||
### Legacy patterns: `ref` and `ref mut`
|
||||
|
||||
In older versions of Rust, `match` would assume that you want to move what is
|
||||
matched. But sometimes, that's not what you wanted. For example:
|
||||
matched. But sometimes, that’s not what you wanted. For example:
|
||||
|
||||
```rust
|
||||
let robot_name = &Some(String::from("Bors"));
|
||||
|
@ -895,7 +895,7 @@ println!("robot_name is: {:?}", robot_name);
|
|||
```
|
||||
|
||||
Here, `robot_name` is a `&Option<String>`. Rust would then complain that
|
||||
`Some(name)` doesn't match up with `&Option<T>`, so you'd have to write this:
|
||||
`Some(name)` doesn’t match up with `&Option<T>`, so you’d have to write this:
|
||||
|
||||
```rust,ignore
|
||||
let robot_name = &Some(String::from("Bors"));
|
||||
|
@ -909,8 +909,8 @@ println!("robot_name is: {:?}", robot_name);
|
|||
```
|
||||
|
||||
Next, Rust would complain that `name` is trying to move the `String` out of
|
||||
the option, but because it's a reference to an option, it's borrowed, and so
|
||||
can't be moved out of. This is where the `ref` keyword comes into play:
|
||||
the option, but because it’s a reference to an option, it’s borrowed, and so
|
||||
can’t be moved out of. This is where the `ref` keyword comes into play:
|
||||
|
||||
```rust
|
||||
let robot_name = &Some(String::from("Bors"));
|
||||
|
@ -923,17 +923,17 @@ match robot_name {
|
|||
println!("robot_name is: {:?}", robot_name);
|
||||
```
|
||||
|
||||
The `ref` keyword is like the opposite of `&` in patterns; this says "please
|
||||
bind `ref` to be a `&String`, don't try to move it out. In other words, the
|
||||
The `ref` keyword is like the opposite of `&` in patterns; this says “please
|
||||
bind `ref` to be a `&String`, don’t try to move it out. In other words, the
|
||||
`&` in `&Some` is matching against a reference, but `ref` *creates* a
|
||||
reference. `ref mut` is like `ref`, but for mutable references.
|
||||
|
||||
Anyway, today's Rust doesn't work like this. If you try to `match` on
|
||||
Anyway, today’s Rust doesn’t work like this. If you try to `match` on
|
||||
something borrowed, then all of the bindings you create will attempt to
|
||||
borrow as well. This means that the original code works as you'd expect.
|
||||
borrow as well. This means that the original code works as you’d expect.
|
||||
|
||||
Because Rust is backwards compatible, we couldn't remove `ref` and `ref mut`,
|
||||
and they're sometimes useful in obscure situations, where you want to
|
||||
Because Rust is backwards compatible, we couldn’t remove `ref` and `ref mut`,
|
||||
and they’re sometimes useful in obscure situations, where you want to
|
||||
partially borrow part of a struct as mutable and another part as immutable.
|
||||
But you may see them in older Rust code, so knowing what they do is still
|
||||
useful.
|
||||
|
|
|
@ -443,7 +443,7 @@ the same lifetime specified in the trait object bounds as those references.
|
|||
|
||||
### The anonymous lifetime
|
||||
|
||||
Let's say that we have a struct that's a wrapper around a string slice, like
|
||||
Let’s say that we have a struct that’s a wrapper around a string slice, like
|
||||
this:
|
||||
|
||||
```rust
|
||||
|
@ -459,7 +459,7 @@ fn foo<'a>(string: &'a str) -> StrWrap<'a> {
|
|||
}
|
||||
```
|
||||
|
||||
But that's a lot of `'a`s! To cut down on some of this noise, we can use the
|
||||
But that’s a lot of `'a`s! To cut down on some of this noise, we can use the
|
||||
anonymous lifetime, `'_`, like this:
|
||||
|
||||
```rust
|
||||
|
@ -469,8 +469,8 @@ fn foo(string: &str) -> StrWrap<'_> {
|
|||
}
|
||||
```
|
||||
|
||||
The `'_` says "use the elidied lifetime here." This means that we can still see
|
||||
that `StrWrap` contains a reference, but we don't need all of the lifetime
|
||||
The `'_` says “use the elidied lifetime here.” This means that we can still see
|
||||
that `StrWrap` contains a reference, but we don’t need all of the lifetime
|
||||
annotations to make sense of it.
|
||||
|
||||
It works in `impl` headers too; for example:
|
||||
|
|
|
@ -85,7 +85,7 @@ implements `Display`.
|
|||
|
||||
Another useful pattern exploits an implementation detail of tuple structs and
|
||||
tuple-struct enum variants. These items use `()` as initialiser syntax, which
|
||||
looks like a function call, and they're actually implemented as functions
|
||||
looks like a function call, and they’re actually implemented as functions
|
||||
returning an instance constructed from their arguments. They can also be called
|
||||
as a function pointer implementing the closure traits, and so can be used
|
||||
similarly to the above:
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
## Macros
|
||||
|
||||
We’ve used macros like `println!` throughout this book but haven’t fully
|
||||
explored what a macro is and how it works. There's a lot more to them,
|
||||
though; "macros" refer to a family of different features in Rust:
|
||||
explored what a macro is and how it works. There’s a lot more to them,
|
||||
though; “macros” refer to a family of different features in Rust:
|
||||
|
||||
* *Declarative* macros with `macro_rules`
|
||||
* *Procedural*, which have three sub-kinds:
|
||||
|
@ -10,7 +10,7 @@ though; "macros" refer to a family of different features in Rust:
|
|||
* Attribute-like macros
|
||||
* Function-like macros
|
||||
|
||||
We'll talk about each of these in turn, but first, why do we even
|
||||
We’ll talk about each of these in turn, but first, why do we even
|
||||
need macros when we already have functions?
|
||||
|
||||
### The Difference Between Macros and Functions
|
||||
|
@ -98,7 +98,7 @@ definition</span>
|
|||
|
||||
The `#[macro_export]` annotation indicates that this macro should be made
|
||||
available whenever the crate in which we’re defining the macro is brought into
|
||||
scope. Without this annotation, the macro can't be brought into scope.
|
||||
scope. Without this annotation, the macro can’t be brought into scope.
|
||||
|
||||
We then start the macro definition with `macro_rules!` and the name of the
|
||||
macro we’re defining *without* the exclamation mark. The name, in this case
|
||||
|
@ -172,7 +172,7 @@ code as declarative macros do.
|
|||
While there are three kinds of procedural macros, they all work in a similar
|
||||
fashion. First, they must reside in their own crate, with a special crate type.
|
||||
This is for complex technical reasons that we hope to eliminate in the future,
|
||||
and so won't discuss here. Second, they all take a form like this:
|
||||
and so won’t discuss here. Second, they all take a form like this:
|
||||
|
||||
```rust,ignore
|
||||
use proc_macro;
|
||||
|
@ -183,24 +183,24 @@ pub fn some_name(input: TokenStream) -> TokenStream {
|
|||
```
|
||||
|
||||
Procedural macros consist of a function, which is how they get their name:
|
||||
"procedure" is a synonym for "function." Why not call them "functional
|
||||
macros"? Well, one of the types is "function-like", and that would get
|
||||
“procedure” is a synonym for “function.” Why not call them “functional
|
||||
macros”? Well, one of the types is “function-like”, and that would get
|
||||
confusing. Anyway, the function takes a `TokenStream` as an input, and
|
||||
produces a `TokenStream` as an output. This is the core of the macro;
|
||||
the source that the macro is operating on makes up the input `TokenStream`,
|
||||
and the code we produce from our macro is the output `TokenStream`.
|
||||
We'll talk more about `TokenStream` when we actually build one of these
|
||||
We’ll talk more about `TokenStream` when we actually build one of these
|
||||
things. Finally, the function has an attribute on it; this attribute
|
||||
says which kind of procedural macro we're creating. We can have multiple
|
||||
says which kind of procedural macro we’re creating. We can have multiple
|
||||
kinds of procedural macros in the same crate.
|
||||
|
||||
Given that the kinds of macros are so similar, we'll start with a custom
|
||||
derive macro, and then in the other sections, we'll explain the small
|
||||
Given that the kinds of macros are so similar, we’ll start with a custom
|
||||
derive macro, and then in the other sections, we’ll explain the small
|
||||
differences that make the other forms different.
|
||||
|
||||
### Custom Derive
|
||||
|
||||
Let's create a crate named `hello_macro` that defines a trait named
|
||||
Let’s create a crate named `hello_macro` that defines a trait named
|
||||
`HelloMacro` with one associated function named `hello_macro`. Rather than
|
||||
making our crate users implement the `HelloMacro` trait for each of their
|
||||
types, we’ll provide a procedural macro so users can annotate their type with
|
||||
|
@ -342,7 +342,7 @@ procedural macro’s purpose.
|
|||
|
||||
We’ve introduced three new crates: `proc_macro`, [`syn`], and [`quote`]. The
|
||||
`proc_macro` crate comes with Rust, so we didn’t need to add that to the
|
||||
dependencies in *Cargo.toml*. The `proc_macro` crate is the compiler's API to
|
||||
dependencies in *Cargo.toml*. The `proc_macro` crate is the compiler’s API to
|
||||
be able to read and manipulate Rust code from our code. The `syn` crate
|
||||
parses Rust code from a string into a data structure that we can perform
|
||||
operations on. The `quote` crate takes `syn` data structures and turns them
|
||||
|
@ -475,7 +475,7 @@ trait implementation.
|
|||
|
||||
Attribute-like macros are similar to custom derive macros, but instead of
|
||||
generating code for `#[derive]`, they allow you to create new, custom
|
||||
attributes of your own. They're also more flexible; derive only works for
|
||||
attributes of your own. They’re also more flexible; derive only works for
|
||||
structs and enums; attributes can go on other places as well, like functions.
|
||||
As an example of using an attribute-like macro, you might have something like
|
||||
this when using a web application framework:
|
||||
|
@ -496,10 +496,10 @@ pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
Here, we have two input `TokenStream`s; the first is for the contents of the
|
||||
attribute itself, that is, the `GET, "/"` stuff. The second is the body of
|
||||
the thing the attribute is attached to, in this case, `fn index() {}` and the
|
||||
rest of the function's body.
|
||||
rest of the function’s body.
|
||||
|
||||
Other than that, they work the same way: create a crate with the `proc-macro`
|
||||
crate type, and you're good to go!
|
||||
crate type, and you’re good to go!
|
||||
|
||||
### Function-like macros
|
||||
|
||||
|
@ -510,7 +510,7 @@ example, an `sql!` macro:
|
|||
let sql = sql!(SELECT * FROM posts WHERE id=1);
|
||||
```
|
||||
|
||||
This macro would parse the SQL statement inside of it and check that it's
|
||||
This macro would parse the SQL statement inside of it and check that it’s
|
||||
syntactically correct. This macro would be defined like this:
|
||||
|
||||
```rust,ignore
|
||||
|
@ -518,5 +518,5 @@ syntactically correct. This macro would be defined like this:
|
|||
pub fn sql(input: TokenStream) -> TokenStream {
|
||||
```
|
||||
|
||||
This is similar to the derive macro's signature: we get in the tokens that are
|
||||
This is similar to the derive macro’s signature: we get in the tokens that are
|
||||
inside of the parentheses, and return the code we wanted to generate.
|
||||
|
|
Loading…
Reference in New Issue