small edits for recently written book chapters

This commit is contained in:
Steve Klabnik 2015-04-21 13:17:43 -04:00
parent 3860240b0e
commit 0070625495
5 changed files with 145 additions and 145 deletions

View File

@ -1,8 +1,8 @@
% Associated Types
Associated types are a powerful part of Rust's type system. They're related to
the idea of a 'type family', in other words, grouping multiple types together. That
description is a bit abstract, so let's dive right into an example. If you want
Associated types are a powerful part of Rusts type system. Theyre related to
the idea of a type family, in other words, grouping multiple types together. That
description is a bit abstract, so lets dive right into an example. If you want
to write a `Graph` trait, you have two types to be generic over: the node type
and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
this:
@ -48,11 +48,11 @@ fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
No need to deal with the `E`dge type here!
Let's go over all this in more detail.
Lets go over all this in more detail.
## Defining associated types
Let's build that `Graph` trait. Here's the definition:
Lets build that `Graph` trait. Heres the definition:
```rust
trait Graph {
@ -86,7 +86,7 @@ trait Graph {
## Implementing associated types
Just like any trait, traits that use associated types use the `impl` keyword to
provide implementations. Here's a simple implementation of Graph:
provide implementations. Heres a simple implementation of Graph:
```rust
# trait Graph {
@ -118,13 +118,13 @@ impl Graph for MyGraph {
This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
gives you an idea of how to implement this kind of thing. We first need three
`struct`s, one for the graph, one for the node, and one for the edge. If it made
more sense to use a different type, that would work as well, we're just going to
more sense to use a different type, that would work as well, were just going to
use `struct`s for all three here.
Next is the `impl` line, which is just like implementing any other trait.
From here, we use `=` to define our associated types. The name the trait uses
goes on the left of the `=`, and the concrete type we're `impl`ementing this
goes on the left of the `=`, and the concrete type were `impl`ementing this
for goes on the right. Finally, we use the concrete types in our function
declarations.

View File

@ -1,9 +1,9 @@
% Closures
Rust not only has named functions, but anonymous functions as well. Anonymous
functions that have an associated environment are called 'closures', because they
functions that have an associated environment are called closures, because they
close over an environment. Rust has a really great implementation of them, as
we'll see.
well see.
# Syntax
@ -15,7 +15,7 @@ let plus_one = |x: i32| x + 1;
assert_eq!(2, plus_one(1));
```
We create a binding, `plus_one`, and assign it to a closure. The closure's
We create a binding, `plus_one`, and assign it to a closure. The closures
arguments go between the pipes (`|`), and the body is an expression, in this
case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line
closures too:
@ -33,7 +33,7 @@ let plus_two = |x| {
assert_eq!(4, plus_two(2));
```
You'll notice a few things about closures that are a bit different than regular
Youll notice a few things about closures that are a bit different than regular
functions defined with `fn`. The first of which is that we did not need to
annotate the types of arguments the closure takes or the values it returns. We
can:
@ -44,13 +44,13 @@ let plus_one = |x: i32| -> i32 { x + 1 };
assert_eq!(2, plus_one(1));
```
But we don't have to. Why is this? Basically, it was chosen for ergonomic reasons.
But we dont have to. Why is this? Basically, it was chosen for ergonomic reasons.
While specifying the full type for named functions is helpful with things like
documentation and type inference, the types of closures are rarely documented
since theyre anonymous, and they dont cause the kinds of error-at-a-distance
that inferring named function types can.
The second is that the syntax is similar, but a bit different. I've added spaces
The second is that the syntax is similar, but a bit different. Ive added spaces
here to make them look a little closer:
```rust
@ -59,11 +59,11 @@ let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
let plus_one_v3 = |x: i32 | x + 1 ;
```
Small differences, but they're similar in ways.
Small differences, but theyre similar in ways.
# Closures and their environment
Closures are called such because they 'close over their environment.' It
Closures are called such because they close over their environment. It
looks like this:
```rust
@ -105,7 +105,7 @@ fn main() {
^
```
A verbose yet helpful error message! As it says, we can't take a mutable borrow
A verbose yet helpful error message! As it says, we cant take a mutable borrow
on `num` because the closure is already borrowing it. If we let the closure go
out of scope, we can:
@ -140,7 +140,7 @@ let takes_nums = || nums;
```
`Vec<T>` has ownership over its contents, and therefore, when we refer to it
in our closure, we have to take ownership of `nums`. It's the same as if we'd
in our closure, we have to take ownership of `nums`. Its the same as if wed
passed `nums` to a function that took ownership of it.
## `move` closures
@ -156,7 +156,7 @@ let owns_num = move |x: i32| x + num;
Now, even though the keyword is `move`, the variables follow normal move semantics.
In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy
of `num`. So what's the difference?
of `num`. So whats the difference?
```rust
let mut num = 5;
@ -171,11 +171,11 @@ assert_eq!(10, num);
```
So in this case, our closure took a mutable reference to `num`, and then when
we called `add_num`, it mutated the underlying value, as we'd expect. We also
we called `add_num`, it mutated the underlying value, as wed expect. We also
needed to declare `add_num` as `mut` too, because were mutating its
environment.
If we change to a `move` closure, it's different:
If we change to a `move` closure, its different:
```rust
let mut num = 5;
@ -203,8 +203,8 @@ you tons of control over what your code does, and closures are no different.
# Closure implementation
Rust's implementation of closures is a bit different than other languages. They
are effectively syntax sugar for traits. You'll want to make sure to have read
Rusts implementation of closures is a bit different than other languages. They
are effectively syntax sugar for traits. Youll want to make sure to have read
the [traits chapter][traits] before this one, as well as the chapter on [trait
objects][trait-objects].
@ -237,9 +237,9 @@ pub trait FnOnce<Args> {
# }
```
You'll notice a few differences between these traits, but a big one is `self`:
Youll notice a few differences between these traits, but a big one is `self`:
`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This
covers all three kinds of `self` via the usual method call syntax. But we've
covers all three kinds of `self` via the usual method call syntax. But weve
split them up into three traits, rather than having a single one. This gives us
a large amount of control over what kind of closures we can take.
@ -253,7 +253,7 @@ Now that we know that closures are traits, we already know how to accept and
return closures: just like any other trait!
This also means that we can choose static vs dynamic dispatch as well. First,
let's write a function which takes something callable, calls it, and returns
lets write a function which takes something callable, calls it, and returns
the result:
```rust
@ -271,7 +271,7 @@ assert_eq!(3, answer);
We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it
suggests: it calls the closure, giving it `1` as an argument.
Let's examine the signature of `call_with_one` in more depth:
Lets examine the signature of `call_with_one` in more depth:
```rust
fn call_with_one<F>(some_closure: F) -> i32
@ -280,7 +280,7 @@ fn call_with_one<F>(some_closure: F) -> i32
```
We take one parameter, and it has the type `F`. We also return a `i32`. This part
isn't interesting. The next part is:
isnt interesting. The next part is:
```rust
# fn call_with_one<F>(some_closure: F) -> i32
@ -292,9 +292,9 @@ Because `Fn` is a trait, we can bound our generic with it. In this case, our clo
takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
is `Fn(i32) -> i32`.
There's one other key point here: because we're bounding a generic with a
trait, this will get monomorphized, and therefore, we'll be doing static
dispatch into the closure. That's pretty neat. In many langauges, closures are
Theres one other key point here: because were bounding a generic with a
trait, this will get monomorphized, and therefore, well be doing static
dispatch into the closure. Thats pretty neat. In many langauges, closures are
inherently heap allocated, and will always involve dynamic dispatch. In Rust,
we can stack allocate our closure environment, and statically dispatch the
call. This happens quite often with iterators and their adapters, which often
@ -320,7 +320,7 @@ to our closure when we pass it to `call_with_one`, so we use `&||`.
Its very common for functional-style code to return closures in various
situations. If you try to return a closure, you may run into an error. At
first, it may seem strange, but we'll figure it out. Here's how you'd probably
first, it may seem strange, but well figure it out. Heres how youd probably
try to return a closure from a function:
```rust,ignore
@ -361,7 +361,7 @@ In order to return something from a function, Rust needs to know what
size the return type is. But since `Fn` is a trait, it could be various
things of various sizes: many different types can implement `Fn`. An easy
way to give something a size is to take a reference to it, as references
have a known size. So we'd write this:
have a known size. So wed write this:
```rust,ignore
fn factory() -> &(Fn(i32) -> Vec<i32>) {
@ -385,7 +385,7 @@ fn factory() -> &(Fn(i32) -> i32) {
```
Right. Because we have a reference, we need to give it a lifetime. But
our `factory()` function takes no arguments, so elision doesn't kick in
our `factory()` function takes no arguments, so elision doesnt kick in
here. What lifetime can we choose? `'static`:
```rust,ignore
@ -414,7 +414,7 @@ error: mismatched types:
```
This error is letting us know that we don't have a `&'static Fn(i32) -> i32`,
This error is letting us know that we dont have a `&'static Fn(i32) -> i32`,
we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
Because each closure generates its own environment `struct` and implementation
@ -422,7 +422,7 @@ of `Fn` and friends, these types are anonymous. They exist just solely for
this closure. So Rust shows them as `closure <anon>`, rather than some
autogenerated name.
But why doesn't our closure implement `&'static Fn`? Well, as we discussed before,
But why doesnt our closure implement `&'static Fn`? Well, as we discussed before,
closures borrow their environment. And in this case, our environment is based
on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime
of the stack frame. So if we returned this closure, the function call would be
@ -445,7 +445,7 @@ assert_eq!(6, answer);
# }
```
We use a trait object, by `Box`ing up the `Fn`. There's just one last problem:
We use a trait object, by `Box`ing up the `Fn`. Theres just one last problem:
```text
error: `num` does not live long enough
@ -471,5 +471,5 @@ assert_eq!(6, answer);
```
By making the inner closure a `move Fn`, we create a new stack frame for our
closure. By `Box`ing it up, we've given it a known size, and allowing it to
closure. By `Box`ing it up, weve given it a known size, and allowing it to
escape our stack frame.

View File

@ -1,16 +1,16 @@
% Crates and Modules
When a project starts getting large, it's considered good software
When a project starts getting large, its considered good software
engineering practice to split it up into a bunch of smaller pieces, and then
fit them together. It's also important to have a well-defined interface, so
fit them together. Its also important to have a well-defined interface, so
that some of your functionality is private, and some is public. To facilitate
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
languages. Hence "Cargo" as the name of Rust's package management tool: you
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 Rusts package management tool: you
ship your crates to others with Cargo. Crates can produce an executable or a
library, depending on the project.
@ -18,10 +18,10 @@ 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
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:
As an example, lets make a *phrases* crate, which will give us various phrases
in different languages. To keep things simple, well stick to greetings and
farewells as two kinds of phrases, and use English and Japanese (日本語) as
two languages for those phrases to be in. Well use this module layout:
```text
+-----------+
@ -47,7 +47,7 @@ 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.
Now that we have a plan, let's define these modules in code. To start,
Now that we have a plan, lets define these modules in code. To start,
generate a new crate with Cargo:
```bash
@ -72,7 +72,7 @@ above.
# Defining Modules
To define each of our modules, we use the `mod` keyword. Let's make our
To define each of our modules, we use the `mod` keyword. Lets make our
`src/lib.rs` look like this:
```
@ -101,7 +101,7 @@ Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules
with double-colon (`::`) notation: our four nested modules are
`english::greetings`, `english::farewells`, `japanese::greetings`, and
`japanese::farewells`. Because these sub-modules are namespaced under their
parent module, the names don't conflict: `english::greetings` and
parent module, the names dont conflict: `english::greetings` and
`japanese::greetings` are distinct, even though their names are both
`greetings`.
@ -116,11 +116,11 @@ build deps examples libphrases-a7448e02a0468eaa.rlib native
```
`libphrase-hash.rlib` is the compiled crate. Before we see how to use this
crate from another crate, let's break it up into multiple files.
crate from another crate, lets break it up into multiple files.
# Multiple file crates
If each crate were just one file, these files would get very large. It's often
If each crate were just one file, these files would get very large. Its often
easier to split up crates into multiple files, and Rust supports this in two
ways.
@ -141,7 +141,7 @@ mod english;
If we do that, Rust will expect to find either a `english.rs` file, or a
`english/mod.rs` file with the contents of our module.
Note that in these files, you don't need to re-declare the module: that's
Note that in these files, you dont need to re-declare the module: thats
already been done with the initial `mod` declaration.
Using these two techniques, we can break up our crate into two directories and
@ -180,7 +180,7 @@ mod japanese;
These two declarations tell Rust to look for either `src/english.rs` and
`src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending
on our preference. In this case, because our modules have sub-modules, we've
on our preference. In this case, because our modules have sub-modules, weve
chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
like this:
@ -192,11 +192,11 @@ mod farewells;
Again, these declarations tell Rust to look for either
`src/english/greetings.rs` and `src/japanese/greetings.rs` or
`src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because
these sub-modules don't have their own sub-modules, we've chosen to make them
these sub-modules dont have their own sub-modules, weve chosen to make them
`src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew!
The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are
both empty at the moment. Let's add some functions.
both empty at the moment. Lets add some functions.
Put this in `src/english/greetings.rs`:
@ -223,7 +223,7 @@ fn hello() -> String {
```
Of course, you can copy and paste this from this web page, or just type
something else. It's not important that you actually put "konnichiwa" to learn
something else. Its not important that you actually put konnichiwa to learn
about the module system.
Put this in `src/japanese/farewells.rs`:
@ -234,17 +234,17 @@ fn goodbye() -> String {
}
```
(This is "Sayōnara", if you're curious.)
(This is Sayōnara, if youre curious.)
Now that we have some functionality in our crate, let's try to use it from
Now that we have some functionality in our crate, lets try to use it from
another crate.
# Importing External Crates
We have a library crate. Let's make an executable crate that imports and uses
We have a library crate. Lets make an executable crate that imports and uses
our library.
Make a `src/main.rs` and put this in it (it won't quite compile yet):
Make a `src/main.rs` and put this in it (it wont quite compile yet):
```rust,ignore
extern crate phrases;
@ -259,7 +259,7 @@ fn main() {
```
The `extern crate` declaration tells Rust that we need to compile and link to
the `phrases` crate. We can then use `phrases`' modules in this one. As we
the `phrases` crate. We can then use `phrases` modules in this one. As we
mentioned earlier, you can use double colons to refer to sub-modules and the
functions inside of them.
@ -267,10 +267,10 @@ Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
rather than a library crate. Our package now has two crates: `src/lib.rs` and
`src/main.rs`. This pattern is quite common for executable crates: most
functionality is in a library crate, and the executable crate uses that
library. This way, other programs can also use the library crate, and it's also
library. This way, other programs can also use the library crate, and its also
a nice separation of concerns.
This doesn't quite work yet, though. We get four errors that look similar to
This doesnt quite work yet, though. We get four errors that look similar to
this:
```bash
@ -287,14 +287,14 @@ note: in expansion of format_args!
phrases/src/main.rs:4:5: 4:76 note: expansion site
```
By default, everything is private in Rust. Let's talk about this in some more
By default, everything is private in Rust. Lets talk about this in some more
depth.
# Exporting a Public Interface
Rust allows you to precisely control which aspects of your interface are
public, and so private is the default. To make things public, you use the `pub`
keyword. Let's focus on the `english` module first, so let's reduce our `src/main.rs`
keyword. Lets focus on the `english` module first, so lets reduce our `src/main.rs`
to just this:
```{rust,ignore}
@ -306,21 +306,21 @@ fn main() {
}
```
In our `src/lib.rs`, let's add `pub` to the `english` module declaration:
In our `src/lib.rs`, lets add `pub` to the `english` module declaration:
```{rust,ignore}
pub mod english;
mod japanese;
```
And in our `src/english/mod.rs`, let's make both `pub`:
And in our `src/english/mod.rs`, lets make both `pub`:
```{rust,ignore}
pub mod greetings;
pub mod farewells;
```
In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration:
In our `src/english/greetings.rs`, lets add `pub` to our `fn` declaration:
```{rust,ignore}
pub fn hello() -> String {
@ -358,12 +358,12 @@ Goodbye in English: Goodbye.
Now that our functions are public, we can use them. Great! However, typing out
`phrases::english::greetings::hello()` is very long and repetitive. Rust has
another keyword for importing names into the current scope, so that you can
refer to them with shorter names. Let's talk about `use`.
refer to them with shorter names. Lets talk about `use`.
# Importing Modules with `use`
Rust has a `use` keyword, which allows us to import names into our local scope.
Let's change our `src/main.rs` to look like this:
Lets change our `src/main.rs` to look like this:
```{rust,ignore}
extern crate phrases;
@ -378,7 +378,7 @@ fn main() {
```
The two `use` lines import each module into the local scope, so we can refer to
the functions by a much shorter name. By convention, when importing functions, it's
the functions by a much shorter name. By convention, when importing functions, its
considered best practice to import the module, rather than the function directly. In
other words, you _can_ do this:
@ -395,7 +395,7 @@ fn main() {
```
But it is not idiomatic. This is significantly more likely to introduce a
naming conflict. In our short program, it's not a big deal, but as it grows, it
naming conflict. In our short program, its not a big deal, but as it grows, it
becomes a problem. If we have conflicting names, Rust will give a compilation
error. For example, if we made the `japanese` functions public, and tried to do
this:
@ -423,7 +423,7 @@ error: aborting due to previous error
Could not compile `phrases`.
```
If we're importing multiple names from the same module, we don't have to type it out
If were importing multiple names from the same module, we dont have to type it out
twice. Instead of this:
```{rust,ignore}
@ -439,11 +439,11 @@ use phrases::english::{greetings, farewells};
## Re-exporting with `pub use`
You don't just use `use` to shorten identifiers. You can also use it inside of your crate
You dont just use `use` to shorten identifiers. You can also use it inside of your crate
to re-export a function inside another module. This allows you to present an external
interface that may not directly map to your internal code organization.
Let's look at an example. Modify your `src/main.rs` to read like this:
Lets look at an example. Modify your `src/main.rs` to read like this:
```{rust,ignore}
extern crate phrases;
@ -494,11 +494,11 @@ mod farewells;
```
The `pub use` declaration brings the function into scope at this part of our
module hierarchy. Because we've `pub use`d this inside of our `japanese`
module hierarchy. Because weve `pub use`d this inside of our `japanese`
module, we now have a `phrases::japanese::hello()` function and a
`phrases::japanese::goodbye()` function, even though the code for them lives in
`phrases::japanese::greetings::hello()` and
`phrases::japanese::farewells::goodbye()`. Our internal organization doesn't
`phrases::japanese::farewells::goodbye()`. Our internal organization doesnt
define our external interface.
Here we have a `pub use` for each function we want to bring into the
@ -507,13 +507,13 @@ everything from `greetings` into the current scope: `pub use self::greetings::*`
What about the `self`? Well, by default, `use` declarations are absolute paths,
starting from your crate root. `self` makes that path relative to your current
place in the hierarchy instead. There's one more special form of `use`: you can
place in the hierarchy instead. Theres one more special form of `use`: you can
`use super::` to reach one level up the tree from your current location. Some
people like to think of `self` as `.` and `super` as `..`, from many shells'
people like to think of `self` as `.` and `super` as `..`, from many shells
display for the current directory and the parent directory.
Outside of `use`, paths are relative: `foo::bar()` refers to a function inside
of `foo` relative to where we are. If that's prefixed with `::`, as in
of `foo` relative to where we are. If thats prefixed with `::`, as in
`::foo::bar()`, it refers to a different `foo`, an absolute path from your
crate root.

View File

@ -1,20 +1,20 @@
% Macros
By now you've learned about many of the tools Rust provides for abstracting and
By now youve learned about many of the tools Rust provides for abstracting and
reusing code. These units of code reuse have a rich semantic structure. For
example, functions have a type signature, type parameters have trait bounds,
and overloaded functions must belong to a particular trait.
This structure means that Rust's core abstractions have powerful compile-time
This structure means that Rusts core abstractions have powerful compile-time
correctness checking. But this comes at the price of reduced flexibility. If
you visually identify a pattern of repeated code, you may find it's difficult
you visually identify a pattern of repeated code, you may find its difficult
or cumbersome to express that pattern as a generic function, a trait, or
anything else within Rust's semantics.
anything else within Rusts semantics.
Macros allow us to abstract at a *syntactic* level. A macro invocation is
Macros allow us to abstract at a syntactic level. A macro invocation is
shorthand for an "expanded" syntactic form. This expansion happens early in
compilation, before any static checking. As a result, macros can capture many
patterns of code reuse that Rust's core abstractions cannot.
patterns of code reuse that Rusts core abstractions cannot.
The drawback is that macro-based code can be harder to understand, because
fewer of the built-in rules apply. Like an ordinary function, a well-behaved
@ -23,8 +23,8 @@ difficult to design a well-behaved macro! Additionally, compiler errors in
macro code are harder to interpret, because they describe problems in the
expanded code, not the source-level form that developers use.
These drawbacks make macros something of a "feature of last resort". That's not
to say that macros are bad; they are part of Rust because sometimes they're
These drawbacks make macros something of a "feature of last resort". Thats not
to say that macros are bad; they are part of Rust because sometimes theyre
needed for truly concise, well-abstracted code. Just keep this tradeoff in
mind.
@ -40,7 +40,7 @@ let x: Vec<u32> = vec![1, 2, 3];
# assert_eq!(x, [1, 2, 3]);
```
This can't be an ordinary function, because it takes any number of arguments.
This cant be an ordinary function, because it takes any number of arguments.
But we can imagine it as syntactic shorthand for
```rust
@ -77,20 +77,20 @@ macro_rules! vec {
# }
```
Whoa, that's a lot of new syntax! Let's break it down.
Whoa, thats a lot of new syntax! Lets break it down.
```ignore
macro_rules! vec { ... }
```
This says we're defining a macro named `vec`, much as `fn vec` would define a
function named `vec`. In prose, we informally write a macro's name with an
This says were defining a macro named `vec`, much as `fn vec` would define a
function named `vec`. In prose, we informally write a macros name with an
exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
syntax and serves to distinguish a macro from an ordinary function.
## Matching
The macro is defined through a series of *rules*, which are pattern-matching
The macro is defined through a series of rules, which are pattern-matching
cases. Above, we had
```ignore
@ -99,13 +99,13 @@ cases. Above, we had
This is like a `match` expression arm, but the matching happens on Rust syntax
trees, at compile time. The semicolon is optional on the last (here, only)
case. The "pattern" on the left-hand side of `=>` is known as a *matcher*.
case. The "pattern" on the left-hand side of `=>` is known as a matcher.
These have [their own little grammar] within the language.
[their own little grammar]: ../reference.html#macros
The matcher `$x:expr` will match any Rust expression, binding that syntax tree
to the *metavariable* `$x`. The identifier `expr` is a *fragment specifier*;
to the metavariable `$x`. The identifier `expr` is a fragment specifier;
the full possibilities are enumerated in the [advanced macros chapter][].
Surrounding the matcher with `$(...),*` will match zero or more expressions,
separated by commas.
@ -158,8 +158,8 @@ Each matched expression `$x` will produce a single `push` statement in the
macro expansion. The repetition in the expansion proceeds in "lockstep" with
repetition in the matcher (more on this in a moment).
Because `$x` was already declared as matching an expression, we don't repeat
`:expr` on the right-hand side. Also, we don't include a separating comma as
Because `$x` was already declared as matching an expression, we dont repeat
`:expr` on the right-hand side. Also, we dont include a separating comma as
part of the repetition operator. Instead, we have a terminating semicolon
within the repeated block.
@ -180,7 +180,7 @@ The outer braces are part of the syntax of `macro_rules!`. In fact, you can use
The inner braces are part of the expanded syntax. Remember, the `vec!` macro is
used in an expression context. To write an expression with multiple statements,
including `let`-bindings, we use a block. If your macro expands to a single
expression, you don't need this extra layer of braces.
expression, you dont need this extra layer of braces.
Note that we never *declared* that the macro produces an expression. In fact,
this is not determined until we use the macro as an expression. With care, you
@ -194,7 +194,7 @@ The repetition operator follows two principal rules:
1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
it contains, in lockstep, and
2. each `$name` must be under at least as many `$(...)*`s as it was matched
against. If it is under more, it'll be duplicated, as appropriate.
against. If it is under more, itll be duplicated, as appropriate.
This baroque macro illustrates the duplication of variables from outer
repetition levels.
@ -219,7 +219,7 @@ fn main() {
}
```
That's most of the matcher syntax. These examples use `$(...)*`, which is a
Thats most of the matcher syntax. These examples use `$(...)*`, which is a
"zero or more" match. Alternatively you can write `$(...)+` for a "one or
more" match. Both forms optionally include a separator, which can be any token
except `+` or `*`.
@ -244,9 +244,9 @@ int main() {
```
After expansion we have `5 * 2 + 3`, and multiplication has greater precedence
than addition. If you've used C macros a lot, you probably know the standard
than addition. If youve used C macros a lot, you probably know the standard
idioms for avoiding this problem, as well as five or six others. In Rust, we
don't have to worry about it.
dont have to worry about it.
```rust
macro_rules! five_times {
@ -261,8 +261,8 @@ fn main() {
The metavariable `$x` is parsed as a single expression node, and keeps its
place in the syntax tree even after substitution.
Another common problem in macro systems is *variable capture*. Here's a C
macro, using [a GNU C extension] to emulate Rust's expression blocks.
Another common problem in macro systems is variable capture. Heres a C
macro, using [a GNU C extension] to emulate Rusts expression blocks.
[a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
@ -275,7 +275,7 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks.
})
```
Here's a simple use case that goes terribly wrong:
Heres a simple use case that goes terribly wrong:
```text
const char *state = "reticulating splines";
@ -315,10 +315,10 @@ fn main() {
```
This works because Rust has a [hygienic macro system][]. Each macro expansion
happens in a distinct *syntax context*, and each variable is tagged with the
syntax context where it was introduced. It's as though the variable `state`
happens in a distinct syntax context, and each variable is tagged with the
syntax context where it was introduced. Its as though the variable `state`
inside `main` is painted a different "color" from the variable `state` inside
the macro, and therefore they don't conflict.
the macro, and therefore they dont conflict.
[hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro
@ -336,7 +336,7 @@ fn main() {
}
```
Instead you need to pass the variable name into the invocation, so it's tagged
Instead you need to pass the variable name into the invocation, so its tagged
with the right syntax context.
```rust
@ -368,7 +368,7 @@ fn main() {
# Recursive macros
A macro's expansion can include more macro invocations, including invocations
A macros expansion can include more macro invocations, including invocations
of the very same macro being expanded. These recursive macros are useful for
processing tree-structured input, as illustrated by this (simplistic) HTML
shorthand:
@ -429,7 +429,7 @@ they are unstable and require feature gates.
Even when Rust code contains un-expanded macros, it can be parsed as a full
[syntax tree][ast]. This property can be very useful for editors and other
tools that process code. It also has a few consequences for the design of
Rust's macro system.
Rusts macro system.
[ast]: glossary.html#abstract-syntax-tree
@ -454,13 +454,13 @@ consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends.
More formally, the macro invocation body must be a sequence of *token trees*.
More formally, the macro invocation body must be a sequence of token trees.
A token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token.
Within a matcher, each metavariable has a *fragment specifier*, identifying
Within a matcher, each metavariable has a fragment specifier, identifying
which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`.
@ -482,7 +482,7 @@ There are additional rules regarding the next token after a metavariable:
* `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token.
These rules provide some flexibility for Rust's syntax to evolve without
These rules provide some flexibility for Rusts syntax to evolve without
breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the
@ -500,7 +500,7 @@ One downside is that scoping works differently for macros, compared to other
constructs in the language.
Definition and expansion of macros both happen in a single depth-first,
lexical-order traversal of a crate's source. So a macro defined at module scope
lexical-order traversal of a crates source. So a macro defined at module scope
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
@ -508,8 +508,8 @@ A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item.
If a module has the `macro_use` attribute, its macros are also visible in its
parent module after the child's `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parent's `mod`
parent module after the childs `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parents `mod`
item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context
@ -524,7 +524,7 @@ If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
there is no `#[macro_use]` attribute then no macros are loaded. Only macros
defined with the `#[macro_export]` attribute may be loaded.
To load a crate's macros *without* linking it into the output, use `#[no_link]`
To load a crates macros without linking it into the output, use `#[no_link]`
as well.
An example:
@ -619,12 +619,12 @@ only appear at the root of your crate, not inside `mod`. This ensures that
The introductory chapter mentioned recursive macros, but it did not give the
full story. Recursive macros are useful for another reason: Each recursive
invocation gives you another opportunity to pattern-match the macro's
invocation gives you another opportunity to pattern-match the macros
arguments.
As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system.
within Rusts macro system.
```rust
macro_rules! bct {
@ -765,9 +765,9 @@ as `unimplemented!` until youre ready to write them.
# Procedural macros
If Rust's macro system can't do what you need, you may want to write a
If Rusts macro system cant do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable,
and bugs can be much harder to track down. 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.

View File

@ -1,15 +1,15 @@
% Trait Objects
When code involves polymorphism, there needs to be a mechanism to determine
which specific version is actually run. This is called 'dispatch.' There are
which specific version is actually run. This is called dispatch. There are
two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
favors static dispatch, it also supports dynamic dispatch through a mechanism
called 'trait objects.'
called trait objects.
## Background
For the rest of this chapter, we'll need a trait and some implementations.
Let's make a simple one, `Foo`. It has one method that is expected to return a
For the rest of this chapter, well need a trait and some implementations.
Lets make a simple one, `Foo`. It has one method that is expected to return a
`String`.
```rust
@ -18,7 +18,7 @@ trait Foo {
}
```
We'll also implement this trait for `u8` and `String`:
Well also implement this trait for `u8` and `String`:
```rust
# trait Foo { fn method(&self) -> String; }
@ -53,7 +53,7 @@ fn main() {
}
```
Rust uses 'monomorphization' to perform static dispatch here. This means that
Rust uses monomorphization to perform static dispatch here. This means that
Rust will create a special version of `do_something()` for both `u8` and
`String`, and then replace the call sites with calls to these specialized
functions. In other words, Rust generates something like this:
@ -82,7 +82,7 @@ fn main() {
This has a great upside: static dispatch allows function calls to be
inlined because the callee is known at compile time, and inlining is
the key to good optimization. Static dispatch is fast, but it comes at
a tradeoff: 'code bloat', due to many copies of the same function
a tradeoff: code bloat, due to many copies of the same function
existing in the binary, one for each type.
Furthermore, compilers arent perfect and may “optimize” code to become slower.
@ -99,7 +99,7 @@ reason.
## Dynamic dispatch
Rust provides dynamic dispatch through a feature called 'trait objects.' Trait
Rust provides dynamic dispatch through a feature called trait objects. Trait
objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
*any* type that implements the given trait, where the precise type can only be
known at runtime.
@ -109,12 +109,12 @@ implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it
(e.g. using `&x` as an argument to a function that takes `&Foo`).
These trait object coercions and casts also work for pointers like `&mut T` to
`&mut Foo` and `Box<T>` to `Box<Foo>`, but that's all at the moment. Coercions
`&mut Foo` and `Box<T>` to `Box<Foo>`, but thats all at the moment. Coercions
and casts are identical.
This operation can be seen as "erasing" the compiler's knowledge about the
This operation can be seen as erasing the compilers knowledge about the
specific type of the pointer, and hence trait objects are sometimes referred to
as "type erasure".
as type erasure.
Coming back to the example above, we can use the same trait to perform dynamic
dispatch with trait objects by casting:
@ -167,7 +167,7 @@ on the heap to store it.
For `Foo`, we would need to have a value that could be at least either a
`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
dependent crates may implement `Foo` (any number of bytes at all). There's no
dependent crates may implement `Foo` (any number of bytes at all). Theres no
way to guarantee that this last point can work if the values are stored without
a pointer, because those other types can be arbitrarily large.
@ -177,14 +177,14 @@ when we are tossing a trait object around, only the size of the pointer itself.
### Representation
The methods of the trait can be called on a trait object via a special record
of function pointers traditionally called a 'vtable' (created and managed by
of function pointers traditionally called a vtable (created and managed by
the compiler).
Trait objects are both simple and complicated: their core representation and
layout is quite straight-forward, but there are some curly error messages and
surprising behaviors to discover.
Let's start simple, with the runtime representation of a trait object. The
Lets start simple, with the runtime representation of a trait object. The
`std::raw` module contains structs with layouts that are the same as the
complicated built-in types, [including trait objects][stdraw]:
@ -199,12 +199,12 @@ pub struct TraitObject {
[stdraw]: ../std/raw/struct.TraitObject.html
That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable"
That is, a trait object like `&Foo` consists of a data pointer and a vtable
pointer.
The data pointer addresses the data (of some unknown type `T`) that the trait
object is storing, and the vtable pointer points to the vtable ("virtual method
table") corresponding to the implementation of `Foo` for `T`.
object is storing, and the vtable pointer points to the vtable (virtual method
table) corresponding to the implementation of `Foo` for `T`.
A vtable is essentially a struct of function pointers, pointing to the concrete
@ -212,7 +212,7 @@ piece of machine code for each method in the implementation. A method call like
`trait_object.method()` will retrieve the correct pointer out of the vtable and
then do a dynamic call of it. For example:
```{rust,ignore}
```rust,ignore
struct FooVtable {
destructor: fn(*mut ()),
size: usize,
@ -261,7 +261,7 @@ static Foo_for_String_vtable: FooVtable = FooVtable {
```
The `destructor` field in each vtable points to a function that will clean up
any resources of the vtable's type, for `u8` it is trivial, but for `String` it
any resources of the vtables type, for `u8` it is trivial, but for `String` it
will free the memory. This is necessary for owning trait objects like
`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
internal type when they go out of scope. The `size` and `align` fields store
@ -270,11 +270,11 @@ essentially unused at the moment since the information is embedded in the
destructor, but will be used in the future, as trait objects are progressively
made more flexible.
Suppose we've got some values that implement `Foo`, then the explicit form of
Suppose weve got some values that implement `Foo`, then the explicit form of
construction and use of `Foo` trait objects might look a bit like (ignoring the
type mismatches: they're all just pointers anyway):
type mismatches: theyre all just pointers anyway):
```{rust,ignore}
```rust,ignore
let a: String = "foo".to_string();
let x: u8 = 1;