Copyedit generics.md and traits.md

Squashed at reviewer's request:

Add heading at the end of the introductory material
Spice up introductory paragraphs a bit
Use quotes instead of <code> for phrase
Remove "other" in "other restrictions" (it's not obvious that any other
restrictions have been mentioned)
"Default methods" is a second-level heading, but is not a subsection of
"Where clause"
Reword "Default methods" introduction: it's not the "last feature" on
this page
This commit is contained in:
Leif Arne Storset 2015-07-25 13:52:14 +02:00
parent 556b0815d7
commit 427736931b
2 changed files with 14 additions and 11 deletions

View file

@ -6,7 +6,7 @@ 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, lets check out some generic code. Rusts
Anyway, enough type theory, lets check out some generic code. Rusts
standard library provides a type, `Option<T>`, thats generic:
```rust
@ -27,7 +27,7 @@ let x: Option<i32> = Some(5);
In the type declaration, we say `Option<i32>`. Note how similar this looks to
`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`.
the right-hand side of the binding, we make a `Some(T)`, where `T` is `5`.
Since thats an `i32`, the two sides match, and Rust is happy. If they didnt
match, wed get an error:

View file

@ -47,8 +47,11 @@ As you can see, the `trait` block looks very similar to the `impl` block,
but we dont define a body, just a type signature. When we `impl` a trait,
we use `impl Trait for Item`, rather than just `impl Item`.
We can use traits to constrain our generics. Consider this function, which
does not compile:
## Traits bounds for generic functions
Traits are useful because they allow a type to make certain promises about its
behavior. Generic functions can exploit this to constrain the types they
accept. Consider this function, which does not compile:
```rust,ignore
fn print_area<T>(shape: T) {
@ -75,7 +78,7 @@ fn print_area<T: HasArea>(shape: T) {
}
```
The syntax `<T: HasArea>` means `any type that implements the HasArea trait`.
The syntax `<T: HasArea>` means “any type that implements the `HasArea` trait.”
Because traits define function type signatures, we can be sure that any type
which implements `HasArea` will have an `.area()` method.
@ -154,8 +157,8 @@ error: the trait `HasArea` is not implemented for the type `_` [E0277]
## Traits bounds for generic structs
Trait constraints also can apply to implementations for generic structs. Just
append the constraint when you declare type parameters. Here is a new type
Your generic structs can also benefit from trait constraints. All you need to
do is append the constraint when you declare type parameters. Here is a new
type `Rectangle<T>` and its operation `is_square()`:
```rust
@ -232,7 +235,7 @@ impl HasArea for i32 {
It is considered poor style to implement methods on such primitive types, even
though it is possible.
This may seem like the Wild West, but there are two other restrictions around
This may seem like the Wild West, but there are two restrictions around
implementing traits that prevent this from getting out of hand. The first is
that if the trait isnt defined in your scope, it doesnt apply. Heres an
example: the standard library provides a [`Write`][write] trait which adds
@ -397,10 +400,10 @@ This shows off the additional feature of `where` clauses: they allow bounds
where the left-hand side is an arbitrary type (`i32` in this case), not just a
plain type parameter (like `T`).
## Default methods
# Default methods
Theres one last feature of traits we should cover: default methods. Its
easiest just to show an example:
If you already know how a typical implementor will define a method, you can
let your trait supply a default:
```rust
trait Foo {