Skip to content

Commit

Permalink
small edits for recently written book chapters
Browse files Browse the repository at this point in the history
  • Loading branch information
steveklabnik committed Apr 21, 2015
1 parent 3860240 commit 0070625
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 145 deletions.
16 changes: 8 additions & 8 deletions src/doc/trpl/associated-types.md
@@ -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:
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.

Expand Down
60 changes: 30 additions & 30 deletions src/doc/trpl/closures.md
@@ -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

Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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 they’re anonymous, and they don’t 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
Expand All @@ -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
Expand Down Expand Up @@ -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:

Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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 we’re 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;
Expand Down Expand Up @@ -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].

Expand Down Expand Up @@ -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.

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -320,7 +320,7 @@ to our closure when we pass it to `call_with_one`, so we use `&||`.

It’s 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
Expand Down Expand Up @@ -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>) {
Expand All @@ -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
Expand Down Expand Up @@ -414,15 +414,15 @@ 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
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
Expand All @@ -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
Expand All @@ -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.

0 comments on commit 0070625

Please sign in to comment.