提交 8f618146 编写于 作者: K Kevin Yap

Standardize punctuation & formatting of TRPL

This commit is an attempt to standardize the use of punctuation and
formatting in "The Rust Programming Language" as discussed in #19823.

- Convert bold text to italicized textcwhen referring to terminology.
- Convert single-quoted text to italicized or double-quoted text,
  depending on context.
- Use double quotes only in the case of scare quotes or quotations.
上级 6354d60e
% Arrays, Vectors, and Slices
Like many programming languages, Rust has list types to represent a sequence of
things. The most basic is the **array**, a fixed-size list of elements of the
things. The most basic is the *array*, a fixed-size list of elements of the
same type. By default, arrays are immutable.
```{rust}
......@@ -32,7 +32,7 @@ for e in a.iter() {
}
```
You can access a particular element of an array with **subscript notation**:
You can access a particular element of an array with *subscript notation*:
```{rust}
let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
......@@ -47,7 +47,7 @@ array, you will get an error: array access is bounds-checked at run-time. Such
errant access is the source of many bugs in other systems programming
languages.
A **vector** is a dynamic or "growable" array, implemented as the standard
A *vector* is a dynamic or "growable" array, implemented as the standard
library type [`Vec<T>`](../std/vec/) (we'll talk about what the `<T>` means
later). Vectors are to arrays what `String` is to `&str`. You can create them
with the `vec!` macro:
......@@ -73,7 +73,7 @@ println!("The length of nums is now {}", nums.len()); // Prints 4
Vectors have many more useful methods.
A **slice** is a reference to (or "view" into) an array. They are useful for
A *slice* is a reference to (or "view" into) an array. They are useful for
allowing safe, efficient access to a portion of an array without copying. For
example, you might want to reference just one line of a file read into memory.
By nature, a slice is not created directly, but from an existing variable.
......
......@@ -2,7 +2,7 @@
So far, we've made lots of functions in Rust, but we've given them all names.
Rust also allows us to create anonymous functions. Rust's anonymous
functions are called **closure**s. By themselves, closures aren't all that
functions are called *closures*. By themselves, closures aren't all that
interesting, but when you combine them with functions that take closures as
arguments, really powerful things are possible.
......@@ -61,7 +61,7 @@ fn main() {
## Moving closures
Rust has a second type of closure, called a **moving closure**. Moving
Rust has a second type of closure, called a *moving closure*. Moving
closures are indicated using the `move` keyword (e.g., `move || x *
x`). The difference between a moving closure and an ordinary closure
is that a moving closure always takes ownership of all variables that
......
......@@ -4,8 +4,8 @@ Now that we have some functions, it's a good idea to learn about comments.
Comments are notes that you leave to other programmers to help explain things
about your code. The compiler mostly ignores them.
Rust has two kinds of comments that you should care about: **line comment**s
and **doc comment**s.
Rust has two kinds of comments that you should care about: *line comments*
and *doc comments*.
```{rust}
// Line comments are anything after '//' and extend to the end of the line.
......
......@@ -6,7 +6,7 @@ strings, but next, let's talk about some more complicated ways of storing data.
## Tuples
The first compound data type we're going to talk about are called **tuple**s.
The first compound data type we're going to talk about are called *tuples*.
Tuples are an ordered list of a fixed size. Like this:
```rust
......@@ -25,10 +25,10 @@ position having a type name rather than the value. Careful readers will also
note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
You haven't seen `&str` as a type before, and we'll discuss the details of
strings later. In systems programming languages, strings are a bit more complex
than in other languages. For now, just read `&str` as "a string slice," and
than in other languages. For now, just read `&str` as a *string slice*, and
we'll learn more soon.
You can access the fields in a tuple through a **destructuring let**. Here's
You can access the fields in a tuple through a *destructuring let*. Here's
an example:
```rust
......@@ -40,8 +40,8 @@ println!("x is {}", x);
Remember before when I said the left-hand side of a `let` statement was more
powerful than just assigning a binding? Here we are. We can put a pattern on
the left-hand side of the `let`, and if it matches up to the right-hand side,
we can assign multiple bindings at once. In this case, `let` 'destructures,'
or 'breaks up,' the tuple, and assigns the bits to three bindings.
we can assign multiple bindings at once. In this case, `let` "destructures,"
or "breaks up," the tuple, and assigns the bits to three bindings.
This pattern is very powerful, and we'll see it repeated more later.
......@@ -83,18 +83,18 @@ fn main() {
}
```
Even though Rust functions can only return one value, a tuple _is_ one value,
that happens to be made up of more than one value. You can also see in this example how you
can destructure a pattern returned by a function, as well.
Even though Rust functions can only return one value, a tuple *is* one value,
that happens to be made up of more than one value. You can also see in this
example how you can destructure a pattern returned by a function, as well.
Tuples are a very simple data structure, and so are not often what you want.
Let's move on to their bigger sibling, structs.
## Structs
A struct is another form of a 'record type,' just like a tuple. There's a
A struct is another form of a *record type*, just like a tuple. There's a
difference: structs give each element that they contain a name, called a
'field' or a 'member.' Check it out:
*field* or a *member*. Check it out:
```rust
struct Point {
......@@ -143,8 +143,7 @@ This will print `The point is at (5, 0)`.
## Tuple Structs and Newtypes
Rust has another data type that's like a hybrid between a tuple and a struct,
called a **tuple struct**. Tuple structs do have a name, but their fields
don't:
called a *tuple struct*. Tuple structs do have a name, but their fields don't:
```{rust}
......@@ -182,7 +181,7 @@ Now, we have actual names, rather than positions. Good names are important,
and with a struct, we have actual names.
There _is_ one case when a tuple struct is very useful, though, and that's a
tuple struct with only one element. We call this a 'newtype,' because it lets
tuple struct with only one element. We call this a *newtype*, because it lets
you create a new type that's a synonym for another one:
```{rust}
......@@ -199,7 +198,7 @@ destructuring `let`.
## Enums
Finally, Rust has a "sum type", an **enum**. Enums are an incredibly useful
Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful
feature of Rust, and are used throughout the standard library. This is an enum
that is provided by the Rust standard library:
......
......@@ -8,17 +8,17 @@ these kinds of things, Rust has a module system.
# Basic terminology: Crates and Modules
Rust has two distinct terms that relate to the module system: "crate" and
"module." A crate is synonymous with a 'library' or 'package' in other
Rust has two distinct terms that relate to the module system: *crate* and
*module*. A crate is synonymous with a *library* or *package* in other
languages. Hence "Cargo" as the name of Rust's package management tool: you
ship your crates to others with Cargo. Crates can produce an executable or a
shared library, depending on the project.
Each crate has an implicit "root module" that contains the code for that crate.
Each crate has an implicit *root module* that contains the code for that crate.
You can then define a tree of sub-modules under that root module. Modules allow
you to partition your code within the crate itself.
As an example, let's make a "phrases" crate, which will give us various phrases
As an example, let's make a *phrases* crate, which will give us various phrases
in different languages. To keep things simple, we'll stick to "greetings" and
"farewells" as two kinds of phrases, and use English and Japanese (日本語) as
two languages for those phrases to be in. We'll use this module layout:
......@@ -45,7 +45,7 @@ two languages for those phrases to be in. We'll use this module layout:
In this example, `phrases` is the name of our crate. All of the rest are
modules. You can see that they form a tree, branching out from the crate
"root", which is the root of the tree: `phrases` itself.
*root*, which is the root of the tree: `phrases` itself.
Now that we have a plan, let's define these modules in code. To start,
generate a new crate with Cargo:
......
......@@ -16,10 +16,10 @@ how to handle each. Then, we'll discuss upgrading failures to panics.
# Failure vs. Panic
Rust uses two terms to differentiate between two forms of error: failure, and
panic. A **failure** is an error that can be recovered from in some way. A
**panic** is an error that cannot be recovered from.
panic. A *failure* is an error that can be recovered from in some way. A
*panic* is an error that cannot be recovered from.
What do we mean by 'recover'? Well, in most cases, the possibility of an error
What do we mean by "recover"? Well, in most cases, the possibility of an error
is expected. For example, consider the `from_str` function:
```{rust,ignore}
......@@ -35,7 +35,7 @@ from_str("hello5world");
```
This won't work. So we know that this function will only work properly for some
inputs. It's expected behavior. We call this kind of error 'failure.'
inputs. It's expected behavior. We call this kind of error a *failure*.
On the other hand, sometimes, there are errors that are unexpected, or which
we cannot recover from. A classic example is an `assert!`:
......@@ -46,7 +46,7 @@ assert!(x == 5);
We use `assert!` to declare that something is true. If it's not true, something
is very wrong. Wrong enough that we can't continue with things in the current
state. Another example is using the `unreachable!()` macro
state. Another example is using the `unreachable!()` macro:
```{rust,ignore}
enum Event {
......@@ -114,7 +114,7 @@ fn main() {
We shouldn't ever hit the `_` case, so we use the `unreachable!()` macro to
indicate this. `unreachable!()` gives a different kind of error than `Result`.
Rust calls these sorts of errors 'panics.'
Rust calls these sorts of errors *panics*.
# Handling errors with `Option` and `Result`
......
......@@ -166,7 +166,7 @@ GitHub](https://github.com/thestinger/rust-snappy).
# Stack management
Rust tasks by default run on a "large stack". This is actually implemented as a
Rust tasks by default run on a *large stack*. This is actually implemented as a
reserving a large segment of the address space and then lazily mapping in pages
as they are needed. When calling an external C function, the code is invoked on
the same stack as the rust stack. This means that there is no extra
......
......@@ -8,7 +8,7 @@ fn main() {
```
This is the simplest possible function declaration. As we mentioned before,
`fn` says 'this is a function,' followed by the name, some parentheses because
`fn` says "this is a function," followed by the name, some parentheses because
this function takes no arguments, and then some curly braces to indicate the
body. Here's a function named `foo`:
......@@ -86,7 +86,7 @@ fn add_one(x: i32) -> i32 {
```
Rust functions return exactly one value, and you declare the type after an
'arrow', which is a dash (`-`) followed by a greater-than sign (`>`).
"arrow," which is a dash (`-`) followed by a greater-than sign (`>`).
You'll note the lack of a semicolon here. If we added it in:
......
......@@ -20,9 +20,9 @@ enum OptionalFloat64 {
```
This is really unfortunate. Luckily, Rust has a feature that gives us a better
way: generics. Generics are called **parametric polymorphism** in type theory,
which means that they are types or functions that have multiple forms ("poly"
is multiple, "morph" is form) over a given parameter ("parametric").
way: generics. Generics are called *parametric polymorphism* in type theory,
which means that they are types or functions that have multiple forms (*poly*
is multiple, *morph* is form) over a given parameter (*parametric*).
Anyway, enough with type theory declarations, let's check out the generic form
of `OptionalInt`. It is actually provided by Rust itself, and looks like this:
......@@ -150,7 +150,7 @@ fn inverse32(x: f32) -> Result<f32, String> {
}
```
Bummer. What we need is a **generic function**. Luckily, we can write one!
Bummer. What we need is a *generic function*. Luckily, we can write one!
However, it won't _quite_ work yet. Before we get into that, let's talk syntax.
A generic version of `inverse` would look something like this:
......
......@@ -111,7 +111,7 @@ Enter the docs. Rust has a page specifically to document the standard library.
You can find that page [here](../std/index.html). There's a lot of information on
that page, but the best part is the search bar. Right up at the top, there's
a box that you can enter in a search term. The search is pretty primitive
right now, but is getting better all the time. If you type 'random' in that
right now, but is getting better all the time. If you type "random" in that
box, the page will update to [this one](../std/index.html?search=random). The very
first result is a link to [`std::rand::random`](../std/rand/fn.random.html). If we
click on that result, we'll be taken to its documentation page.
......@@ -147,7 +147,7 @@ explained. We then added in a `let` expression to create a variable binding
named `secret_number`, and we printed out its result.
Also, you may wonder why we are using `%` on the result of `rand::random()`.
This operator is called 'modulo', and it returns the remainder of a division.
This operator is called *modulo*, and it returns the remainder of a division.
By taking the modulo of the result of `rand::random()`, we're limiting the
values to be between 0 and 99. Then, we add one to the result, making it from 1
to 100. Using modulo can give you a very, very small bias in the result, but
......@@ -608,8 +608,8 @@ out that I guessed 76. Run the program a few times, and verify that guessing
the number works, as well as guessing a number too small.
The Rust compiler helped us out quite a bit there! This technique is called
"lean on the compiler", and it's often useful when working on some code. Let
the error messages help guide you towards the correct types.
"leaning on the compiler", and it's often useful when working on some code.
Let the error messages help guide you towards the correct types.
Now we've got most of the game working, but we can only make one guess. Let's
change that by adding loops!
......
......@@ -66,7 +66,7 @@ it explain itself to you:
TOML is very similar to INI, but with some extra goodies.
Anyway, there are two **table**s in this file: `package` and `bin`. The first
Anyway, there are two *tables* in this file: `package` and `bin`. The first
tells Cargo metadata about your package. The second tells Cargo that we're
interested in building a binary, not a library (though we could do both!), as
well as what it is named.
......
......@@ -67,7 +67,7 @@ fn main() {
}
```
These lines define a **function** in Rust. The `main` function is special:
These lines define a *function* in Rust. The `main` function is special:
it's the beginning of every Rust program. The first line says "I'm declaring a
function named `main`, which takes no arguments and returns nothing." If there
were arguments, they would go inside the parentheses (`(` and `)`), and because
......@@ -91,7 +91,7 @@ spaces, not tabs. Please configure your editor of choice to insert four spaces
with the tab key. We provide some [sample configurations for various
editors](https://github.com/rust-lang/rust/tree/master/src/etc).
The second point is the `println!()` part. This is calling a Rust **macro**,
The second point is the `println!()` part. This is calling a Rust *macro*,
which is how metaprogramming is done in Rust. If it were a function instead, it
would look like this: `println()`. For our purposes, we don't need to worry
about this difference. Just know that sometimes, you'll see a `!`, and that
......@@ -102,19 +102,19 @@ last thing to mention: Rust's macros are significantly different from C macros,
if you've used those. Don't be scared of using macros. We'll get to the details
eventually, you'll just have to trust us for now.
Next, `"Hello, world!"` is a **string**. Strings are a surprisingly complicated
topic in a systems programming language, and this is a **statically allocated**
Next, `"Hello, world!"` is a *string*. Strings are a surprisingly complicated
topic in a systems programming language, and this is a *statically allocated*
string. We will talk more about different kinds of allocation later. We pass
this string as an argument to `println!`, which prints the string to the
screen. Easy enough!
Finally, the line ends with a semicolon (`;`). Rust is an **expression
oriented** language, which means that most things are expressions. The `;` is
Finally, the line ends with a semicolon (`;`). Rust is an *expression
oriented* language, which means that most things are expressions. The `;` is
used to indicate that this expression is over, and the next one is ready to
begin. Most lines of Rust code end with a `;`. We will cover this in-depth
later in the guide.
Finally, actually **compiling** and **running** our program. We can compile
Finally, actually *compiling* and *running* our program. We can compile
with our compiler, `rustc`, by passing it the name of our source file:
```{bash}
......@@ -147,7 +147,7 @@ This prints out our `Hello, world!` text to our terminal.
If you come from a dynamically typed language like Ruby, Python, or JavaScript,
you may not be used to these two steps being separate. Rust is an
**ahead-of-time compiled language**, which means that you can compile a
*ahead-of-time compiled language*, which means that you can compile a
program, give it to someone else, and they don't need to have Rust installed.
If you give someone a `.rb` or `.py` or `.js` file, they need to have
Ruby/Python/JavaScript installed, but you just need one command to both compile
......
......@@ -4,7 +4,7 @@ Rust's take on `if` is not particularly complex, but it's much more like the
`if` you'll find in a dynamically typed language than in a more traditional
systems language. So let's talk about it, to make sure you grasp the nuances.
`if` is a specific form of a more general concept, the 'branch.' The name comes
`if` is a specific form of a more general concept, the *branch*. The name comes
from a branch in a tree: a decision point, where depending on a choice,
multiple paths can be taken.
......@@ -70,7 +70,7 @@ make no sense. But in Rust, `if` is an expression, which means that it returns
a value. We can then use this value to initialize the binding.
Speaking of which, bindings are a kind of the first of Rust's two statements.
The proper name is a **declaration statement**. So far, `let` is the only kind
The proper name is a *declaration statement*. So far, `let` is the only kind
of declaration statement we've seen. Let's talk about that some more.
In some languages, variable bindings can be written as expressions, not just
......@@ -95,7 +95,7 @@ expression, although its value is not particularly useful. Unlike C, where an
assignment evaluates to the assigned value (e.g. `5` in the previous example),
in Rust the value of an assignment is the unit type `()` (which we'll cover later).
The second kind of statement in Rust is the **expression statement**. Its
The second kind of statement in Rust is the *expression statement*. Its
purpose is to turn any expression into a statement. In practical terms, Rust's
grammar expects statements to follow other statements. This means that you use
semicolons to separate expressions from each other. This means that Rust
......@@ -103,7 +103,7 @@ looks a lot like most other languages that require you to use semicolons
at the end of every line, and you will see semicolons at the end of almost
every line of Rust code you see.
What is this exception that makes us say 'almost?' You saw it already, in this
What is this exception that makes us say "almost"? You saw it already, in this
code:
```{rust}
......@@ -129,7 +129,7 @@ Note the semicolons after the 10 and 15. Rust will give us the following error:
error: mismatched types: expected `i32` but found `()` (expected i32 but found ())
```
We expected an integer, but we got `()`. `()` is pronounced 'unit', and is a
We expected an integer, but we got `()`. `()` is pronounced *unit*, and is a
special type in Rust's type system. In Rust, `()` is _not_ a valid value for a
variable of type `i32`. It's only a valid value for variables of the type `()`,
which aren't very useful. Remember how we said statements don't return a value?
......
......@@ -11,7 +11,7 @@ for x in range(0i, 10i) {
```
Now that you know more Rust, we can talk in detail about how this works. The
`range` function returns an **iterator**. An iterator is something that we can
`range` function returns an *iterator*. An iterator is something that we can
call the `.next()` method on repeatedly, and it gives us a sequence of things.
Like this:
......@@ -101,19 +101,19 @@ So, now that we've established that `range` is often not what you want, let's
talk about what you do want instead.
There are three broad classes of things that are relevant here: iterators,
**iterator adapters**, and **consumers**. Here's some definitions:
*iterator adapters*, and *consumers*. Here's some definitions:
* 'iterators' give you a sequence of values.
* 'iterator adapters' operate on an iterator, producing a new iterator with a
* *iterators* give you a sequence of values.
* *iterator adapters* operate on an iterator, producing a new iterator with a
different output sequence.
* 'consumers' operate on an iterator, producing some final set of values.
* *consumers* operate on an iterator, producing some final set of values.
Let's talk about consumers first, since you've already seen an iterator,
`range`.
## Consumers
A 'consumer' operates on an iterator, returning some kind of value or values.
A *consumer* operates on an iterator, returning some kind of value or values.
The most common consumer is `collect()`. This code doesn't quite compile,
but it shows the intention:
......@@ -161,9 +161,9 @@ let sum = range(1i, 4i)
`fold()` is a consumer that looks like this:
`fold(base, |accumulator, element| ...)`. It takes two arguments: the first
is an element called the "base". The second is a closure that itself takes two
arguments: the first is called the "accumulator," and the second is an
"element." Upon each iteration, the closure is called, and the result is the
is an element called the *base*. The second is a closure that itself takes two
arguments: the first is called the *accumulator*, and the second is an
*element*. Upon each iteration, the closure is called, and the result is the
value of the accumulator on the next iteration. On the first iteration, the
base is the value of the accumulator.
......@@ -205,7 +205,7 @@ see why consumers matter.
As we've said before, an iterator is something that we can call the
`.next()` method on repeatedly, and it gives us a sequence of things.
Because you need to call the method, this means that iterators
are **lazy** and don't need to generate all of the values upfront.
are *lazy* and don't need to generate all of the values upfront.
This code, for example, does not actually generate the numbers
`1-100`, and just creates a value that represents the sequence:
......@@ -252,7 +252,7 @@ we need to talk about with regards to iterators. Let's get to it!
## Iterator adapters
"Iterator adapters" take an iterator and modify it somehow, producing
*Iterator adapters* take an iterator and modify it somehow, producing
a new iterator. The simplest one is called `map`:
```{rust,ignore}
......
......@@ -46,7 +46,7 @@ Rust does not have the "C-style" `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers.
We'll talk more about `for` when we cover **iterator**s, later in the Guide.
We'll talk more about `for` when we cover *iterators*, later in the Guide.
## `while`
......
......@@ -571,4 +571,4 @@ If Rust's macro system can't do what you need, you may want to write a
macros, this is significantly more work, the interfaces are much less stable,
and the warnings about debugging apply ten-fold. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called "procedural macros" for this reason.
extension plugins are sometimes called *procedural macros* for this reason.
......@@ -20,13 +20,13 @@ match x {
}
```
`match` takes an expression and then branches based on its value. Each 'arm' of
`match` takes an expression and then branches based on its value. Each *arm* of
the branch is of the form `val => expression`. When the value matches, that arm's
expression will be evaluated. It's called `match` because of the term 'pattern
matching', which `match` is an implementation of.
So what's the big advantage here? Well, there are a few. First of all, `match`
enforces 'exhaustiveness checking'. Do you see that last arm, the one with the
enforces *exhaustiveness checking*. Do you see that last arm, the one with the
underscore (`_`)? If we remove that arm, Rust will give us an error:
```text
......@@ -36,7 +36,7 @@ error: non-exhaustive patterns: `_` not covered
In other words, Rust is trying to tell us we forgot a value. Because `x` is an
integer, Rust knows that it can have a number of different values – for example,
`6`. Without the `_`, however, there is no arm that could match, and so Rust refuses
to compile. `_` acts like a 'catch-all arm'. If none of the other arms match,
to compile. `_` acts like a *catch-all arm*. If none of the other arms match,
the arm with `_` will, and since we have this catch-all arm, we now have an arm
for every possible value of `x`, and so our program will compile successfully.
......
......@@ -7,8 +7,8 @@ can be awkward. Consider this code:
baz(bar(foo(x)));
```
We would read this left-to right, and so we see 'baz bar foo.' But this isn't the
order that the functions would get called in, that's inside-out: 'foo bar baz.'
We would read this left-to right, and so we see "baz bar foo." But this isn't the
order that the functions would get called in, that's inside-out: "foo bar baz."
Wouldn't it be nice if we could do this instead?
```{rust,ignore}
......@@ -16,7 +16,7 @@ x.foo().bar().baz();
```
Luckily, as you may have guessed with the leading question, you can! Rust provides
the ability to use this **method call syntax** via the `impl` keyword.
the ability to use this *method call syntax* via the `impl` keyword.
Here's how it works:
......@@ -82,7 +82,7 @@ fn main() {
}
```
This **static method** builds a new `Circle` for us. Note that static methods
This *static method* builds a new `Circle` for us. Note that static methods
are called with the `Struct::method()` syntax, rather than the `ref.method()`
syntax.
......@@ -3,15 +3,15 @@
This guide presents Rust's ownership system. This is one of Rust's most unique
and compelling features, with which Rust developers should become quite
acquainted. Ownership is how Rust achieves its largest goal, memory safety.
The ownership system has a few distinct concepts: **ownership**, **borrowing**,
and **lifetimes**. We'll talk about each one in turn.
The ownership system has a few distinct concepts: *ownership*, *borrowing*,
and *lifetimes*. We'll talk about each one in turn.
# Meta
Before we get to the details, two important notes about the ownership system.
Rust has a focus on safety and speed. It accomplishes these goals through many
"zero cost abstractions," which means that in Rust, abstractions cost as little
*zero-cost abstractions*, which means that in Rust, abstractions cost as little
as possible in order to make them work. The ownership system is a prime example
of a zero cost abstraction. All of the analysis we'll talk about in this guide
is _done at compile time_. You do not pay any run-time cost for any of these
......@@ -31,14 +31,14 @@ With that in mind, let's learn about ownership.
# Ownership
At its core, ownership is about 'resources.' For the purposes of the vast
At its core, ownership is about *resources*. For the purposes of the vast
majority of this guide, we will talk about a specific resource: memory. The
concept generalizes to any kind of resource, like a file handle, but to make it
more concrete, we'll focus on memory.
When your program allocates some memory, it needs some way to deallocate that
memory. Imagine a function `foo` that allocates four bytes of memory, and then
never deallocates that memory. We call this problem 'leaking' memory, because
never deallocates that memory. We call this problem *leaking* memory, because
each time we call `foo`, we're allocating another four bytes. Eventually, with
enough calls to `foo`, we will run our system out of memory. That's no good. So
we need some way for `foo` to deallocate those four bytes. It's also important
......@@ -50,7 +50,7 @@ times is bad. The counts must match.
There's one other important detail with regards to allocating memory. Whenever
we request some amount of memory, what we are given is a handle to that memory.
This handle (often called a 'pointer', when we're referring to memory) is how
This handle (often called a *pointer*, when we're referring to memory) is how
we interact with the allocated memory. As long as we have that handle, we can
do something with the memory. Once we're done with the handle, we're also done
with the memory, as we can't do anything useful without a handle to it.
......@@ -74,8 +74,8 @@ The call to `malloc` allocates some memory. The call to `free` deallocates the
memory. There's also bookkeeping about allocating the correct amount of memory.
Rust combines these two aspects of allocating memory (and other resources) into
a concept called 'ownership.' Whenever we request some memory, that handle we
receive is called the 'owning handle.' Whenever that handle goes out of scope,
a concept called *ownership*. Whenever we request some memory, that handle we
receive is called the *owning handle*. Whenever that handle goes out of scope,
Rust knows that you cannot do anything with the memory anymore, and so
therefore deallocates the memory for you. Here's the equivalent example in
Rust:
......@@ -171,8 +171,8 @@ This code will compile and run just fine. Now, we return a `box`, and so the
ownership is transferred back to `y` in `main`. We only have ownership for the
duration of our function before giving it back. This pattern is very common,
and so Rust introduces a concept to describe a handle which temporarily refers
to something another handle owns. It's called "borrowing," and it's done with
"references", designated by the `&` symbol.
to something another handle owns. It's called *borrowing*, and it's done with
*references*, designated by the `&` symbol.
# Borrowing
......@@ -191,11 +191,11 @@ contents. But then we give ownership right back.
In the physical world, you can give one of your possessions to someone for a
short period of time. You still own your possession, you're just letting someone
else use it for a while. We call that 'lending' something to someone, and that
person is said to be 'borrowing' that something from you.
else use it for a while. We call that *lending* something to someone, and that
person is said to be *borrowing* that something from you.
Rust's ownership system also allows an owner to lend out a handle for a limited
period. This is also called 'borrowing.' Here's a version of `add_one` which
period. This is also called *borrowing*. Here's a version of `add_one` which
borrows its argument rather than taking ownership:
```rust
......@@ -219,11 +219,11 @@ complicated, however. For example, imagine this set of operations:
4. You decide to use the resource.
Uh oh! Your reference is pointing to an invalid resource. This is called a
"dangling pointer" or "use after free," when the resource is memory.
*dangling pointer* or "use after free," when the resource is memory.
To fix this, we have to make sure that step four never happens after step
three. The ownership system in Rust does this through a concept called
"lifetimes," which describe the scope that a reference is valid for.
*lifetimes*, which describe the scope that a reference is valid for.
Let's look at that function which borrows an `int` again:
......@@ -233,7 +233,7 @@ fn add_one(num: &int) -> int {
}
```
Rust has a feature called 'lifetime elision,' which allows you to not write
Rust has a feature called *lifetime elision*, which allows you to not write
lifetime annotations in certain circumstances. This is one of them. We will
cover the others later. Without eliding the lifetimes, `add_one` looks like
this:
......@@ -244,7 +244,7 @@ fn add_one<'a>(num: &'a int) -> int {
}
```
The `'a` is called a **lifetime**. Most lifetimes are used in places where
The `'a` is called a *lifetime*. Most lifetimes are used in places where
short names like `'a`, `'b` and `'c` are clearest, but it's often useful to
have more descriptive names. Let's dig into the syntax in a bit more detail:
......@@ -362,7 +362,7 @@ name is the first step towards being able to talk about it.
## 'static
The lifetime named 'static' is a special lifetime. It signals that something
The lifetime named *static* is a special lifetime. It signals that something
has the lifetime of the entire program. Most Rust programmers first come across
`'static` when dealing with strings:
......@@ -456,14 +456,14 @@ thread-safe counterpart of `Rc<T>`.
## Lifetime Elision
Earlier, we mentioned 'lifetime elision,' a feature of Rust which allows you to
Earlier, we mentioned *lifetime elision*, a feature of Rust which allows you to
not write lifetime annotations in certain circumstances. All references have a
lifetime, and so if you elide a lifetime (like `&T` instead of `&'a T`), Rust
will do three things to determine what those lifetimes should be.
When talking about lifetime elision, we use the term 'input lifetime' and
'output lifetime'. An 'input lifetime' is a lifetime associated with a parameter
of a function, and an 'output lifetime' is a lifetime associated with the return
When talking about lifetime elision, we use the term *input lifetime* and
*output lifetime*. An *input lifetime* is a lifetime associated with a parameter
of a function, and an *output lifetime* is a lifetime associated with the return
value of a function. For example, this function has an input lifetime:
```{rust,ignore}
......
......@@ -5,7 +5,7 @@ then with `match` statements. Let's go on a whirlwind tour of all of the things
patterns can do!
A quick refresher: you can match against literals directly, and `_` acts as an
'any' case:
*any* case:
```{rust}
let x = 1i;
......@@ -72,7 +72,7 @@ match x {
}
```
You can introduce **match guards** with `if`:
You can introduce *match guards* with `if`:
```{rust}
enum OptionalInt {
......
......@@ -29,7 +29,7 @@ information.
`rustc` can load compiler plugins, which are user-provided libraries that
extend the compiler's behavior with new syntax extensions, lint checks, etc.
A plugin is a dynamic library crate with a designated "registrar" function that
A plugin is a dynamic library crate with a designated *registrar* function that
registers extensions with `rustc`. Other crates can use these extensions by
loading the plugin crate with `#[plugin] extern crate`. See the
[`rustc::plugin`](../rustc/plugin/index.html) documentation for more about the
......
......@@ -23,7 +23,7 @@ languages, so it's important to understand them.
When you create a new variable binding, you're giving a name to a value that's
stored at a particular location on the stack. (If you're not familiar with the
"heap" vs. "stack", please check out [this Stack Overflow
*heap* vs. *stack*, please check out [this Stack Overflow
question](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap),
as the rest of this guide assumes you know the difference.) Like this:
......@@ -43,7 +43,7 @@ refer to `x`, we get the corresponding value. Hence, `x` is `5`.
Let's introduce a pointer. In some languages, there is just one type of
'pointer,' but in Rust, we have many types. In this case, we'll use a Rust
**reference**, which is the simplest kind of pointer.
*reference*, which is the simplest kind of pointer.
```{rust}
let x = 5i;
......@@ -90,7 +90,7 @@ hello.rs:6 println!("{}", x + z);
^
```
We can **dereference** the pointer by using the `*` operator. Dereferencing a
We can *dereference* the pointer by using the `*` operator. Dereferencing a
pointer means accessing the value at the location stored in the pointer. This
will work:
......@@ -105,8 +105,8 @@ println!("{}", x + *z);
It prints `13`.
That's it! That's all pointers are: they point to some memory location. Not
much else to them. Now that we've discussed the 'what' of pointers, let's
talk about the 'why.'
much else to them. Now that we've discussed the *what* of pointers, let's
talk about the *why*.
## Pointer uses
......@@ -168,7 +168,7 @@ Even in a language which is pass by value, `i` will be `5` at the comment. You
see, because the argument `x` is a pointer, we do send a copy over to `foo`,
but because it points at a memory location, which we then assign to, the
original value is still changed. This pattern is called
'pass-reference-by-value.' Tricky!
*pass-reference-by-value*. Tricky!
## Common pointer problems
......@@ -209,7 +209,7 @@ as `make_pointer` returns. But we return a pointer to its memory location, and
so back in `main`, we try to use that pointer, and it's a very similar
situation to our first one. Setting invalid memory locations is bad.
As one last example of a big problem with pointers, **aliasing** can be an
As one last example of a big problem with pointers, *aliasing* can be an
issue. Two pointers are said to alias when they point at the same location
in memory. Like this:
......@@ -248,7 +248,7 @@ it's worth it to not have the problems that simple pointers have.
# References
The most basic type of pointer that Rust has is called a 'reference.' Rust
The most basic type of pointer that Rust has is called a *reference*. Rust
references look like this:
```{rust}
......@@ -340,8 +340,8 @@ let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time
Despite their complete safety, a reference's representation at runtime is the
same as that of an ordinary pointer in a C program. They introduce zero
overhead. The compiler does all safety checks at compile time. The theory that
allows for this was originally called **region pointers**. Region pointers
evolved into what we know today as **lifetimes**.
allows for this was originally called *region pointers*. Region pointers
evolved into what we know today as *lifetimes*.
Here's the simple explanation: would you expect this code to compile?
......@@ -355,7 +355,7 @@ fn main() {
Probably not. That's because you know that the name `x` is valid from where
it's declared to when it goes out of scope. In this case, that's the end of
the `main` function. So you know this code will cause an error. We call this
duration a 'lifetime'. Let's try a more complex example:
duration a *lifetime*. Let's try a more complex example:
```{rust}
fn main() {
......@@ -474,7 +474,7 @@ those contents.
# Boxes
`Box<T>` is Rust's 'boxed pointer' type. Boxes provide the simplest form of
`Box<T>` is Rust's *boxed pointer* type. Boxes provide the simplest form of
heap allocation in Rust. Creating a box looks like this:
```{rust}
......@@ -496,10 +496,10 @@ they go out of scope:
```
However, boxes do _not_ use reference counting or garbage collection. Boxes are
what's called an **affine type**. This means that the Rust compiler, at compile
what's called an *affine type*. This means that the Rust compiler, at compile
time, determines when the box comes into and goes out of scope, and inserts the
appropriate calls there. Furthermore, boxes are a specific kind of affine type,
known as a **region**. You can read more about regions [in this paper on the
known as a *region*. You can read more about regions [in this paper on the
Cyclone programming
language](http://www.cs.umd.edu/projects/cyclone/papers/cyclone-regions.pdf).
......@@ -560,7 +560,7 @@ fn main() {
}
```
In this case, Rust knows that `x` is being 'borrowed' by the `add_one()`
In this case, Rust knows that `x` is being *borrowed* by the `add_one()`
function, and since it's only reading the value, allows it.
We can borrow `x` multiple times, as long as it's not simultaneous:
......@@ -606,7 +606,7 @@ and occasionally, when returning data.
### Recursive data structures
Sometimes, you need a recursive data structure. The simplest is known as a
'cons list':
*cons list*:
```{rust}
......
......@@ -103,7 +103,7 @@ line of input, though it might also fail to do so. This could happen if our prog
isn't running in a terminal, but as part of a cron job, or some other context
where there's no standard input. Because of this, `read_line` returns a type
very similar to our `OptionalInt`: an `IoResult<T>`. We haven't talked about
`IoResult<T>` yet because it is the **generic** form of our `OptionalInt`.
`IoResult<T>` yet because it is the *generic* form of our `OptionalInt`.
Until then, you can think of it as being the same thing, just for any type –
not just `i32`s.
......
......@@ -6,14 +6,14 @@ focus. Any time you have a data structure of variable size, things can get
tricky, and strings are a re-sizable data structure. That being said, Rust's
strings also work differently than in some other systems languages, such as C.
Let's dig into the details. A **string** is a sequence of Unicode scalar values
Let's dig into the details. A *string* is a sequence of Unicode scalar values
encoded as a stream of UTF-8 bytes. All strings are guaranteed to be
validly encoded UTF-8 sequences. Additionally, strings are not null-terminated
and can contain null bytes.
Rust has two main types of strings: `&str` and `String`.
The first kind is a `&str`. This is pronounced a 'string slice.' String literals
The first kind is a `&str`. These are called *string slices*. String literals
are of the type `&str`:
```{rust}
......
......@@ -73,8 +73,8 @@ with it. For this, we use *channels*. A channel is simply a pair of endpoints:
one for sending messages and another for receiving messages.
The simplest way to create a channel is to use the `channel` function to create a
`(Sender, Receiver)` pair. In Rust parlance, a **sender** is a sending endpoint
of a channel, and a **receiver** is the receiving endpoint. Consider the following
`(Sender, Receiver)` pair. In Rust parlance, a *sender* is a sending endpoint
of a channel, and a *receiver* is the receiving endpoint. Consider the following
example of calculating two results concurrently:
```{rust,ignore}
......
......@@ -294,9 +294,9 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
It works!
The current convention is to use the `test` module to hold your "unit"-style
The current convention is to use the `test` module to hold your "unit-style"
tests. Anything that just tests one small bit of functionality makes sense to
go here. But what about "integration"-style tests instead? For that, we have
go here. But what about "integration-style" tests instead? For that, we have
the `tests` directory
# The `tests` directory
......
......@@ -65,7 +65,7 @@ error: type `T` does not implement any method in scope named `area`
```
Because `T` can be any type, we can't be sure that it implements the `area`
method. But we can add a **trait constraint** to our generic `T`, ensuring
method. But we can add a *trait constraint* to our generic `T`, ensuring
that it does:
```{rust}
......@@ -269,7 +269,7 @@ if we tried to implement `Float`, a trait provided by Rust, for `int`, we could
not, because both the trait and the type aren't in our crate.
One last thing about traits: generic functions with a trait bound use
**monomorphization** ("mono": one, "morph": form), so they are statically
*monomorphization* (*mono*: one, *morph*: form), so they are statically
dispatched. What's that mean? Well, let's take a look at `print_area` again:
```{rust,ignore}
......@@ -313,5 +313,5 @@ fn main() {
The names don't actually change to this, it's just for illustration. But
as you can see, there's no overhead of deciding which version to call here,
hence 'statically dispatched.' The downside is that we have two copies of
hence *statically dispatched*. The downside is that we have two copies of
the same function, so our binary is a little bit larger.
......@@ -78,7 +78,7 @@ let ref_2: &mut u8 = unsafe { mem::transmute(&mut *ref_1) };
## Raw pointers
Rust offers two additional pointer types "raw pointers", written as
Rust offers two additional pointer types (*raw pointers*), written as
`*const T` and `*mut T`. They're an approximation of C's `const T*` and `T*`
respectively; indeed, one of their most common uses is for FFI,
interfacing with external C libraries.
......@@ -418,11 +418,12 @@ specify some extra info about the inline assembly:
Current valid options are:
1. **volatile** - specifying this is analogous to `__asm__ __volatile__ (...)` in gcc/clang.
2. **alignstack** - certain instructions expect the stack to be
1. *volatile* - specifying this is analogous to
`__asm__ __volatile__ (...)` in gcc/clang.
2. *alignstack* - certain instructions expect the stack to be
aligned a certain way (i.e SSE) and specifying this indicates to
the compiler to insert its usual stack alignment code
3. **intel** - use intel syntax instead of the default AT&T.
3. *intel* - use intel syntax instead of the default AT&T.
# Avoiding the standard library
......
% Variable bindings
The first thing we'll learn about are 'variable bindings.' They look like this:
The first thing we'll learn about are *variable bindings*. They look like this:
```{rust}
fn main() {
......@@ -12,9 +12,9 @@ Putting `fn main() {` in each example is a bit tedious, so we'll leave that out
in the future. If you're following along, make sure to edit your `main()`
function, rather than leaving it off. Otherwise, you'll get an error.
In many languages, this is called a 'variable.' But Rust's variable bindings
In many languages, this is called a *variable*. But Rust's variable bindings
have a few tricks up their sleeves. Rust has a very powerful feature called
'pattern matching' that we'll get into detail with later, but the left
*pattern matching* that we'll get into detail with later, but the left
hand side of a `let` expression is a full pattern, not just a variable name.
This means we can do things like:
......@@ -28,7 +28,7 @@ So let's just keep this in the back of our minds as we go forward.
Rust is a statically typed language, which means that we specify our types up
front. So why does our first example compile? Well, Rust has this thing called
"type inference." If it can figure out what the type of something is, Rust
*type inference*. If it can figure out what the type of something is, Rust
doesn't require you to actually type it out.
We can add the type if we want to, though. Types come after a colon (`:`):
......@@ -53,7 +53,7 @@ Note the similarities between this annotation and the syntax you use with `let`.
Including these kinds of comments is not idiomatic Rust, but we'll occasionally
include them to help you understand what the types that Rust infers are.
By default, bindings are **immutable**. This code will not compile:
By default, bindings are *immutable*. This code will not compile:
```{ignore}
let x = 5;
......@@ -162,7 +162,7 @@ talk about this stuff we've added to `println!`.
If you include two curly braces (`{}`, some call them moustaches...) in your
string to print, Rust will interpret this as a request to interpolate some sort
of value. **String interpolation** is a computer science term that means "stick
of value. *String interpolation* is a computer science term that means "stick
in the middle of a string." We add a comma, and then `x`, to indicate that we
want `x` to be the value we're interpolating. The comma is used to separate
arguments we pass to functions and macros, if you're passing more than one.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册