doc: Minor tutorial improvements
This commit is contained in:
parent
2f451a7bd7
commit
73b2a932b7
|
@ -213,8 +213,8 @@ fn main() {
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
The `let` keyword, introduces a local variable. By default, variables
|
The `let` keyword introduces a local variable. Variables are immutable
|
||||||
are immutable. `let mut` can be used to introduce a local variable
|
by default, so `let mut` can be used to introduce a local variable
|
||||||
that can be reassigned.
|
that can be reassigned.
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
|
@ -229,14 +229,17 @@ while count < 10 {
|
||||||
|
|
||||||
Although Rust can almost always infer the types of local variables, it
|
Although Rust can almost always infer the types of local variables, it
|
||||||
can help readability to specify a variable's type by following it with
|
can help readability to specify a variable's type by following it with
|
||||||
a colon, then the type name. Local variables may shadow earlier
|
a colon, then the type name.
|
||||||
declarations, making the earlier variables inaccessible.
|
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
let my_favorite_value: float = 57.8;
|
let my_favorite_value: float = 57.8;
|
||||||
let my_favorite_value: int = my_favorite_value as int;
|
let my_favorite_value: int = my_favorite_value as int;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
Local variables may shadow earlier declarations, as in the previous
|
||||||
|
example in which `my_favorite_value` is first declared as a `float`
|
||||||
|
then a second `my_favorite_value` is declared as an int.
|
||||||
|
|
||||||
Rust identifiers follow the same rules as C; they start with an alphabetic
|
Rust identifiers follow the same rules as C; they start with an alphabetic
|
||||||
character or an underscore, and after that may contain any sequence of
|
character or an underscore, and after that may contain any sequence of
|
||||||
alphabetic characters, numbers, or underscores. The preferred style is to
|
alphabetic characters, numbers, or underscores. The preferred style is to
|
||||||
|
@ -1632,8 +1635,9 @@ fn contains(v: &[int], elt: int) -> bool {
|
||||||
# Generics
|
# Generics
|
||||||
|
|
||||||
Throughout this tutorial, we've been defining functions that act only on
|
Throughout this tutorial, we've been defining functions that act only on
|
||||||
single data types. With type parameters we can also define functions that
|
specific data types. With type parameters we can also define functions whose
|
||||||
may be invoked on multiple types.
|
arguments represent generic types, and which can be invoked with a variety
|
||||||
|
of types. Consider a generic `map` function.
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
fn map<T, U>(vector: &[T], function: fn(v: &T) -> U) -> ~[U] {
|
fn map<T, U>(vector: &[T], function: fn(v: &T) -> U) -> ~[U] {
|
||||||
|
@ -1653,7 +1657,7 @@ each other.
|
||||||
Inside a generic function, the names of the type parameters
|
Inside a generic function, the names of the type parameters
|
||||||
(capitalized by convention) stand for opaque types. You can't look
|
(capitalized by convention) stand for opaque types. You can't look
|
||||||
inside them, but you can pass them around. Note that instances of
|
inside them, but you can pass them around. Note that instances of
|
||||||
generic types are almost always passed by pointer. For example, the
|
generic types are often passed by pointer. For example, the
|
||||||
parameter `function()` is supplied with a pointer to a value of type
|
parameter `function()` is supplied with a pointer to a value of type
|
||||||
`T` and not a value of type `T` itself. This ensures that the
|
`T` and not a value of type `T` itself. This ensures that the
|
||||||
function works with the broadest set of types possible, since some
|
function works with the broadest set of types possible, since some
|
||||||
|
@ -1679,11 +1683,11 @@ These declarations produce valid types like `Set<int>`, `Stack<int>`
|
||||||
and `Maybe<int>`.
|
and `Maybe<int>`.
|
||||||
|
|
||||||
Generic functions in Rust are compiled to very efficient runtime code
|
Generic functions in Rust are compiled to very efficient runtime code
|
||||||
through a process called _monomorphisation_. This big word just means
|
through a process called _monomorphisation_. This is a fancy way of
|
||||||
that, for each generic function you call, the compiler generates a
|
saying that, for each generic function you call, the compiler
|
||||||
specialized version that is optimized specifically for the argument
|
generates a specialized version that is optimized specifically for the
|
||||||
types. In this respect Rust's generics have similar performance
|
argument types. In this respect Rust's generics have similar
|
||||||
characteristics to C++ templates.
|
performance characteristics to C++ templates.
|
||||||
|
|
||||||
## Traits
|
## Traits
|
||||||
|
|
||||||
|
@ -1748,13 +1752,10 @@ types by the compiler, and may not be overridden:
|
||||||
|
|
||||||
## Declaring and implementing traits
|
## Declaring and implementing traits
|
||||||
|
|
||||||
A trait consists of a set of methods, or may be empty, as is the case
|
A trait consists of a set of methods, without bodies, or may be empty,
|
||||||
with `Copy`, `Send`, and `Const`. A method is a function that
|
as is the case with `Copy`, `Send`, and `Const`. For example, we could
|
||||||
can be applied to a `self` value and a number of arguments, using the
|
declare the trait `Printable` for things that can be printed to the
|
||||||
dot notation: `self.foo(arg1, arg2)`.
|
console, with a single method:
|
||||||
|
|
||||||
For example, we could declare the trait `Printable` for things that
|
|
||||||
can be printed to the console, with a single method:
|
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
trait Printable {
|
trait Printable {
|
||||||
|
@ -1762,9 +1763,12 @@ trait Printable {
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
To actually implement a trait for a given type, the `impl` form is
|
Traits may be implemented for specific types with [impls]. An impl
|
||||||
used. This defines implementations of `Printable` for the `int` and
|
that implements a trait includes the name of the trait at the start of
|
||||||
`~str` types.
|
the definition, as in the following impls of `Printable` for `int`
|
||||||
|
and `~str`.
|
||||||
|
|
||||||
|
[impls]: #functions-and-methods
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
# trait Printable { fn print(); }
|
# trait Printable { fn print(); }
|
||||||
|
@ -1780,14 +1784,10 @@ impl ~str: Printable {
|
||||||
# (~"foo").print();
|
# (~"foo").print();
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
Given these, we may call `1.print()` to print `"1"`, or
|
Methods defined in an implementation of a trait may be called just as
|
||||||
`(~"foo").print()` to print `"foo"` again, as with . This is basically a form of
|
any other method, using dot notation, as in `1.print()`. Traits may
|
||||||
static overloading—when the Rust compiler sees the `print` method
|
themselves contain type parameters. A trait for generalized sequence
|
||||||
call, it looks for an implementation that matches the type with a
|
types might look like the following:
|
||||||
method that matches the name, and simply calls that.
|
|
||||||
|
|
||||||
Traits may themselves contain type parameters. A trait for
|
|
||||||
generalized sequence types might look like the following:
|
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
trait Seq<T> {
|
trait Seq<T> {
|
||||||
|
|
Loading…
Reference in New Issue