auto merge of #20782 : iKevinY/rust/trpl-formatting, r=steveklabnik
Here's my PR for the changes discussed in #19823. I decided to leave `_these_` types of italics the way there were because it differentiates the use of italics for emphasis from `*key term*` italics. Otherwise, bolded terms have been changed to italics, and single and double quotes have been changed appropriately, depending on their context (my judgement may not be the best, though). r? @steveklabnik (congratulations on #19897 being finalized and merged, by the way!)
This commit is contained in:
commit
9205d74fe0
@ -1,7 +1,7 @@
|
||||
% 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`
|
||||
|
||||
|
@ -575,4 +575,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
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
% 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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user