mirror of
https://github.com/rust-lang-cn/book-cn.git
synced 2025-01-23 15:40:27 +08:00
Small wording tweaks, mostly removing 'you'
This commit is contained in:
parent
b168c614a2
commit
6bef3b89cf
@ -7,10 +7,10 @@ different capabilities and costs, and choosing an appropriate one for the
|
||||
situation you're in is a skill you'll develop over time. In this chapter, we'll
|
||||
go over three collections which are used very often in Rust programs:
|
||||
|
||||
* A *Vector* allows you to store a variable number of values next to each other.
|
||||
* A *Vector* allows us to store a variable number of values next to each other.
|
||||
* A *String* is a collection of characters. We've seen `String` before, but
|
||||
we'll talk about it in depth now.
|
||||
* A *HashMap* allows you to associate a value with a particular key.
|
||||
* A *HashMap* allows us to associate a value with a particular key.
|
||||
|
||||
There are more specialized variants of each of these data structures for
|
||||
particular situations, but these are the most fundamental and common. We're
|
||||
|
@ -1,26 +1,26 @@
|
||||
## Vectors
|
||||
|
||||
The first type we'll look at is `Vec<T>`, also known as a *vector*. Vectors
|
||||
allow you to store more than one value in a single data structure that puts all
|
||||
allow us to store more than one value in a single data structure that puts all
|
||||
the values next to each other in memory.
|
||||
|
||||
### Creating a New Vector
|
||||
|
||||
To create a new vector, you can call the `new` function:
|
||||
To create a new vector, we can call the `new` function:
|
||||
|
||||
```rust
|
||||
let v: Vec<i32> = Vec::new();
|
||||
```
|
||||
|
||||
You'll note that we added a type annotation here. Because we don't actually do
|
||||
Note that we added a type annotation here. Since we don't actually do
|
||||
anything with the vector, Rust doesn't know what kind of elements we intend to
|
||||
store. This is an important point. Vectors are homogenous: they may store many
|
||||
values, but those values must all be the same type. Vectors are generic over
|
||||
the type you store inside them (we'll talk about Generics more throroughly in
|
||||
the type stored inside them (we'll talk about Generics more throroughly in
|
||||
Chapter XX), and the angle brackets here tell Rust that this vector will hold
|
||||
elements of the `i32` type.
|
||||
|
||||
That said, in real code, you very rarely need to do this type annotation since
|
||||
That said, in real code, we very rarely need to do this type annotation since
|
||||
Rust can infer the type of value we want to store once we insert values. Let's
|
||||
look at how to modify a vector next.
|
||||
|
||||
@ -100,10 +100,10 @@ let does_not_exist = v.get(100);
|
||||
|
||||
With the `[]`s, Rust will cause a `panic!`. With the `get` method, it will
|
||||
instead return `None` without `panic!`ing. Deciding which way to access
|
||||
elements in a vector depends on whether you consider an attempted access past
|
||||
the end of the vector to be an error, in which case you would want the `panic!`
|
||||
elements in a vector depends on whether we consider an attempted access past
|
||||
the end of the vector to be an error, in which case we'd want the `panic!`
|
||||
behavior, or whether this will happen occasionally under normal circumstances
|
||||
and your code will have logic to handle getting `Some(&element)` or `None`.
|
||||
and our code will have logic to handle getting `Some(&element)` or `None`.
|
||||
|
||||
Once we have a valid reference, the borrow checker will enforce the ownership
|
||||
and borrowing rules we covered in Chapter 4 in order to ensure this and other
|
||||
|
@ -9,16 +9,16 @@ Strings are a common place for new Rustaceans to get stuck. This is due to a
|
||||
combination of three things: Rust's propensity for making sure to expose
|
||||
possible errors, strings being a more complicated data structure than many
|
||||
programmers give them credit for, and UTF-8. These things combine in a way that
|
||||
can seem difficult when you're used to other languages.
|
||||
can seem difficult coming from other languages.
|
||||
|
||||
Before we can dig into those things, we need to talk about what exactly we even
|
||||
mean by the word 'string'. Rust-the-language has only one string type: `&str`.
|
||||
We talked about these string slices in Chapter 4: they're a reference to some
|
||||
UTF-8 encoded string data stored somewhere else. String literals, for example,
|
||||
are stored in the binary output of your program, and are therefore string
|
||||
slices.
|
||||
Before we can dig into those aspects, we need to talk about what exactly we
|
||||
even mean by the word 'string'. Rust actually only has one string type in the
|
||||
core language itself: `&str`. We talked about these string slices in Chapter 4:
|
||||
they're a reference to some UTF-8 encoded string data stored somewhere else.
|
||||
String literals, for example, are stored in the binary output of the program,
|
||||
and are therefore string slices.
|
||||
|
||||
Rust's standard library also provides a type called `String`. This is a
|
||||
Rust's standard library is what provides the type called `String`. This is a
|
||||
growable, mutable, owned, UTF-8 encoded string type. When Rustaceans talk about
|
||||
'strings' in Rust, they usually mean "`String` and `&str`". This chapter is
|
||||
largely about `String`, and these two types are used heavily in Rust's standard
|
||||
@ -26,12 +26,12 @@ library. Both `String` and string slices are UTF-8 encoded.
|
||||
|
||||
Rust's standard library also includes a number of other string types, such as
|
||||
`OsString`, `OsStr`, `CString`, and `CStr`. Library crates may provide even
|
||||
more options for storing string data. As you can see from the `*String`/`*Str`
|
||||
naming, they often provide an owned and borrowed variant, just like
|
||||
`String`/`&str`. These string types may store different encodings or be
|
||||
represented in memory in a different way, for example. We won't be talking
|
||||
about these other string types in this chapter; see their API documentation for
|
||||
more about how to use them and when each is appropriate.
|
||||
more options for storing string data. Similarly to the `*String`/`*Str` naming,
|
||||
they often provide an owned and borrowed variant, just like `String`/`&str`.
|
||||
These string types may store different encodings or be represented in memory in
|
||||
a different way, for example. We won't be talking about these other string
|
||||
types in this chapter; see their API documentation for more about how to use
|
||||
them and when each is appropriate.
|
||||
|
||||
### Creating a New String
|
||||
|
||||
@ -42,8 +42,8 @@ starting with creating one. Similarly, `String` has `new`:
|
||||
let s = String::new();
|
||||
```
|
||||
|
||||
Often, you have some initial data that you'd like to start the string off with.
|
||||
For that, there's the `.to_string()` method:
|
||||
Often, we'll have some initial data that we'd like to start the string off with.
|
||||
For that, there's the `to_string` method:
|
||||
|
||||
```rust
|
||||
let data = "initial contents";
|
||||
@ -54,13 +54,13 @@ let s = data.to_string();
|
||||
let s = "initial contents".to_string();
|
||||
```
|
||||
|
||||
You'll also see this form sometimes:
|
||||
This form is equivalent to using `to_string`:
|
||||
|
||||
```rust
|
||||
let s = String::from("Initial contents");
|
||||
```
|
||||
|
||||
Because strings are used for so many things, there are many different generic
|
||||
Since strings are used for so many things, there are many different generic
|
||||
APIs that make sense for strings. There are a lot of options, and some of them
|
||||
can feel redundant because of this, but they all have their place! In this
|
||||
case, `String::from` and `.to_string` end up doing the exact same thing, so
|
||||
@ -68,8 +68,8 @@ which you choose is a matter of style. Some people use `String::from` for
|
||||
literals, and `.to_string` for variable bindings. Most Rust style is pretty
|
||||
uniform, but this specific question is one of the most debated.
|
||||
|
||||
Don't forget that strings are UTF-8 encoded, so you can include any
|
||||
properly encoded data in them:
|
||||
Remember that strings are UTF-8 encoded, so we can include any properly encoded
|
||||
data in them:
|
||||
|
||||
```rust
|
||||
let hello = "السلام عليكم";
|
||||
@ -91,7 +91,7 @@ A `String` can be changed and can grow in size, just like a `Vec` can.
|
||||
|
||||
#### Push
|
||||
|
||||
You can grow a `String` by using the `push_str` method to append another
|
||||
We can grow a `String` by using the `push_str` method to append another
|
||||
string:
|
||||
|
||||
```rust
|
||||
@ -110,7 +110,7 @@ s.push('l');
|
||||
|
||||
`s` will contain "lol" after this point.
|
||||
|
||||
You can make any `String` contain the empty string with the `clear` method:
|
||||
We can make any `String` contain the empty string with the `clear` method:
|
||||
|
||||
```rust
|
||||
let mut s = String::from("Noooooooooooooooooooooo!");
|
||||
@ -121,7 +121,7 @@ Now `s` will be the empty string, "".
|
||||
|
||||
#### Concatenation
|
||||
|
||||
Often, you'll want to combine two strings together. One way is to use the `+`
|
||||
Often, we'll want to combine two strings together. One way is to use the `+`
|
||||
operator:
|
||||
|
||||
```rust
|
||||
@ -144,11 +144,11 @@ signature of the method would be if `add` was defined specifically for
|
||||
`String`. This signature gives us the clues we need in order to understand the
|
||||
tricky bits of `+`.
|
||||
|
||||
First of all, you'll notice that `s2` has an `&`. This is because of the `s`
|
||||
argument in the `add` function: you can only add a `&str` to a `String`, you
|
||||
can't add two `String`s together. Remember back in Chapter 4 when we talked
|
||||
about how `&String` will coerce to `&str`: we write `&s2` so that the `String`
|
||||
will coerce to the proper type, `&str`.
|
||||
First of all, `s2` has an `&`. This is because of the `s` argument in the `add`
|
||||
function: we can only add a `&str` to a `String`, we can't add two `String`s
|
||||
together. Remember back in Chapter 4 when we talked about how `&String` will
|
||||
coerce to `&str`: we write `&s2` so that the `String` will coerce to the proper
|
||||
type, `&str`.
|
||||
|
||||
Secondly, `add` takes ownership of `self`, which we can tell because `self`
|
||||
does *not* have an `&` in the signature. This means `s1` in the above example
|
||||
@ -159,7 +159,7 @@ new one, this statement actually takes ownership of `s1`, appends a copy of
|
||||
like it's making a lot of copies, but isn't: the implementation is more
|
||||
efficient than copying.
|
||||
|
||||
If you need to concatenate multiple strings, this behavior of `+` gets
|
||||
If we need to concatenate multiple strings, this behavior of `+` gets
|
||||
unwieldy:
|
||||
|
||||
```rust
|
||||
@ -245,7 +245,7 @@ let answer = &h[0];
|
||||
```
|
||||
|
||||
What should the value of `answer` be? Should it be `З`, the first letter? When
|
||||
you encode `З` in UTF-8, the first byte is `208`, and the second is `151`. So
|
||||
encoded in UTF-8, the first byte of `З` is `208`, and the second is `151`. So
|
||||
should `answer` be `208`? `208` is not a valid character on its own, though.
|
||||
Plus, for latin letters, this would not return the answer most people would
|
||||
expect: `&"hello"[0]` would then return `104`, not `h`.
|
||||
@ -277,8 +277,8 @@ get this:
|
||||
```
|
||||
|
||||
Four elements! It turns out that even within 'grapheme cluster', there are
|
||||
multiple ways of grouping things. Have we convinced you strings are actually
|
||||
really complicated yet?
|
||||
multiple ways of grouping things. Convinced that strings are actually really
|
||||
complicated yet?
|
||||
|
||||
Another reason that indexing into a `String` to get a character is not available
|
||||
is that indexing operations are expected to always be fast. This isn't possible
|
||||
@ -292,7 +292,7 @@ we cannot directly do this.
|
||||
### Slicing Strings
|
||||
|
||||
However, indexing the bytes of a string is very useful, and is not expected to
|
||||
be fast. While you can't use `[]` with a single number, you _can_ use `[]` with
|
||||
be fast. While we can't use `[]` with a single number, we _can_ use `[]` with
|
||||
a range to create a string slice from particular bytes:
|
||||
|
||||
```rust
|
||||
|
@ -35,7 +35,7 @@ of type `i32` and values of type `&str`. Like vectors, HashMaps are homogenous:
|
||||
all of the keys must have the same type, and all of the values must have the
|
||||
same type.
|
||||
|
||||
If you have a vector of tuples, you can convert it into a HashMap with the
|
||||
If we have a vector of tuples, we can convert it into a HashMap with the
|
||||
`collect` method. The first element in each tuple will be the key, and the
|
||||
second element will be the value:
|
||||
|
||||
@ -123,7 +123,7 @@ This will print:
|
||||
|
||||
#### Overwriting a Value
|
||||
|
||||
If you insert a key and a value, then insert that key with a different value, the value associated with that key will be replaced. Even though this code calls `insert` twice, the HashMap will only contain one key/value pair, since we're inserting with the key `1` both times:
|
||||
If we insert a key and a value, then insert that key with a different value, the value associated with that key will be replaced. Even though this code calls `insert` twice, the HashMap will only contain one key/value pair, since we're inserting with the key `1` both times:
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
@ -176,7 +176,7 @@ println!("{:?}", map);
|
||||
The `or_insert` method on `Entry` does exactly this: returns the value for the
|
||||
`Entry`'s key if it exists, and if not, inserts its argument as the new value
|
||||
for the `Entry`'s key and returns that. This is much cleaner than writing the
|
||||
logic yourself, and in addition, plays more nicely with the borrow checker.
|
||||
logic ourselves, and in addition, plays more nicely with the borrow checker.
|
||||
|
||||
This code will print `{1: "hello", 2: "world"}`. The first call to `entry` will
|
||||
insert the key `2` with the value "world", since `2` doesn't have a value
|
||||
|
Loading…
Reference in New Issue
Block a user