doc: Trim down the tutorial a little more
This commit is contained in:
parent
9eaaceb9f0
commit
df34fe917a
127
doc/tutorial.md
127
doc/tutorial.md
@ -303,14 +303,6 @@ The double-colon (`::`) is used as a module separator, so
|
||||
`io::println` means 'the thing named `println` in the module
|
||||
named `io`.
|
||||
|
||||
Rust will normally emit warnings about unused variables. These can be
|
||||
suppressed by using a variable name that starts with an underscore.
|
||||
|
||||
~~~~
|
||||
fn this_warns(x: int) {}
|
||||
fn this_doesnt(_x: int) {}
|
||||
~~~~
|
||||
|
||||
## Variable declaration
|
||||
|
||||
The `let` keyword, as we've seen, introduces a local variable. Local
|
||||
@ -319,11 +311,11 @@ a local variable that can be reassigned. Global constants can be
|
||||
defined with `const`:
|
||||
|
||||
~~~~
|
||||
const repeat: int = 5;
|
||||
const REPEAT: int = 5;
|
||||
fn main() {
|
||||
let hi = "Hi!";
|
||||
let mut count = 0;
|
||||
while count < repeat {
|
||||
while count < REPEAT {
|
||||
io::println(hi);
|
||||
count += 1;
|
||||
}
|
||||
@ -340,28 +332,6 @@ let my_favorite_value: int = my_favorite_value as int;
|
||||
|
||||
## Types
|
||||
|
||||
The `-> bool` in the `is_four` example is the way a function's return
|
||||
type is written. For functions that do not return a meaningful value
|
||||
(these conceptually return nil in Rust), you can optionally say `->
|
||||
()` (`()` is how nil is written), but usually the return annotation is
|
||||
simply left off, as in the `fn main() { ... }` examples we've seen
|
||||
earlier.
|
||||
|
||||
Every argument to a function must have its type declared (for example,
|
||||
`x: int`). Inside the function, type inference will be able to
|
||||
automatically deduce the type of most locals (generic functions, which
|
||||
we'll come back to later, will occasionally need additional
|
||||
annotation). Locals can be written either with or without a type
|
||||
annotation:
|
||||
|
||||
~~~~
|
||||
// The type of this vector will be inferred based on its use.
|
||||
let x = [];
|
||||
# vec::map(x, fn&(&&_y:int) -> int { _y });
|
||||
// Explicitly say this is a vector of zero integers.
|
||||
let y: [int * 0] = [];
|
||||
~~~~
|
||||
|
||||
The basic types are written like this:
|
||||
|
||||
`()`
|
||||
@ -407,16 +377,16 @@ more detail later on (the `T`s here stand for any other type):
|
||||
`@T`, `~T`, `&T`
|
||||
: Pointer types.
|
||||
|
||||
The size of some types can vary when your program runs. Because of this, you
|
||||
don't manipulate them only by pointer, never directly. For instance, you
|
||||
can't refer to a string (`str`); instead you refer to a pointer to a string
|
||||
(`@str`, `~str`, or `&str`). These *dynamically-sized* types const of:
|
||||
Some types can only be manipulated by pointer, never directly. For instance,
|
||||
you cannot refer to a string (`str`); instead you refer to a pointer to a
|
||||
string (`@str`, `~str`, or `&str`). These *dynamically-sized* types consist
|
||||
of:
|
||||
|
||||
`fn(arg1: T1, arg2: T2) -> T3`
|
||||
: Function types.
|
||||
|
||||
`str`
|
||||
: String type. A string contains a UTF-8 encoded sequence of characters.
|
||||
: String type (in UTF-8).
|
||||
|
||||
`[T]`
|
||||
: Vector with unknown size (also called a slice).
|
||||
@ -437,6 +407,28 @@ error. Read about [single-variant enums](#single_variant_enum)
|
||||
further on if you need to create a type name that's not just a
|
||||
synonym.
|
||||
|
||||
## Using types
|
||||
|
||||
The `-> bool` in the `is_four` example is the way a function's return
|
||||
type is written. For functions that do not return a meaningful value,
|
||||
you can optionally say `-> ()`, but usually the return annotation is simply
|
||||
left off, as in the `fn main() { ... }` examples we've seen earlier.
|
||||
|
||||
Every argument to a function must have its type declared (for example,
|
||||
`x: int`). Inside the function, type inference will be able to
|
||||
automatically deduce the type of most locals (generic functions, which
|
||||
we'll come back to later, will occasionally need additional
|
||||
annotation). Locals can be written either with or without a type
|
||||
annotation:
|
||||
|
||||
~~~~
|
||||
// The type of this vector will be inferred based on its use.
|
||||
let x = [];
|
||||
# vec::map(x, fn&(&&_y:int) -> int { _y });
|
||||
// Explicitly say this is a vector of zero integers.
|
||||
let y: [int * 0] = [];
|
||||
~~~~
|
||||
|
||||
## Numeric literals
|
||||
|
||||
Integers can be written in decimal (`144`), hexadecimal (`0x90`), and
|
||||
@ -478,20 +470,20 @@ between double quotes (`"hello"`). Rust strings may contain newlines.
|
||||
|
||||
## Operators
|
||||
|
||||
Rust's set of operators contains very few surprises. Binary arithmetic
|
||||
is done with `*`, `/`, `%`, `+`, and `-` (multiply, divide, remainder,
|
||||
plus, minus). `-` is also a unary prefix operator that does negation. As in C,
|
||||
the bit operators `>>`, `<<`, `&`, `|`, and `^` are supported.
|
||||
Rust's set of operators contains very few surprises. Arithmetic is done with
|
||||
`*`, `/`, `%`, `+`, and `-` (multiply, divide, remainder, plus, minus). `-` is
|
||||
also a unary prefix operator that does negation. As in C, the bit operators
|
||||
`>>`, `<<`, `&`, `|`, and `^` are also supported.
|
||||
|
||||
Note that, if applied an integer value, `!` inverts all the bits.
|
||||
Note that, if applied to an integer value, `!` flips all the bits (like `~` in
|
||||
C).
|
||||
|
||||
The comparison operators are the traditional `==`, `!=`, `<`, `>`,
|
||||
`<=`, and `>=`. Short-circuiting (lazy) boolean operators are written
|
||||
`&&` (and) and `||` (or).
|
||||
|
||||
For type casting, Rust uses the binary `as` operator, which has high
|
||||
precedence, just lower than multiplication and division. It takes an
|
||||
expression on the left side, and a type on the right side, and will,
|
||||
For type casting, Rust uses the binary `as` operator. It takes an
|
||||
expression on the left side and a type on the right side and will,
|
||||
if a meaningful conversion exists, convert the result of the
|
||||
expression to the given type.
|
||||
|
||||
@ -508,11 +500,12 @@ more likely to be what you expect (unless you are a C veteran).
|
||||
|
||||
## Syntax extensions
|
||||
|
||||
*Syntax extensions* are special syntax that is not built into the language,
|
||||
but are instead provided by the libraries. To make it clear when a syntax
|
||||
extension is being used, their names all end with `!`. The standard library
|
||||
defines a few syntax extensions. The most useful one is `fmt!`, a
|
||||
`sprintf`-style text formatter that is expanded at compile time.
|
||||
*Syntax extensions* are special forms that are not built into the language,
|
||||
but are instead provided by the libraries. To make it clear to the reader when
|
||||
a syntax extension is being used, the names of all syntax extensions end with
|
||||
`!`. The standard library defines a few syntax extensions, the most useful of
|
||||
which is `fmt!`, a `sprintf`-style text formatter that is expanded at compile
|
||||
time.
|
||||
|
||||
~~~~
|
||||
io::println(fmt!("%s is %d", ~"the answer", 42));
|
||||
@ -524,7 +517,8 @@ don't match the types of the arguments.
|
||||
|
||||
[pf]: http://en.cppreference.com/w/cpp/io/c/fprintf
|
||||
|
||||
You can define your own syntax extensions via macros.
|
||||
You can define your own syntax extensions with the macro system, which is out
|
||||
of scope of this tutorial.
|
||||
|
||||
# Control structures
|
||||
|
||||
@ -581,8 +575,8 @@ construct when it is finished.
|
||||
The part to the left of the arrow `=>` is called the *pattern*. Literals are
|
||||
valid patterns and will match only their own value. The pipe operator
|
||||
(`|`) can be used to assign multiple patterns to a single arm. Ranges
|
||||
of numeric literal patterns can be expressed with `..`. The underscore
|
||||
(`_`) is a wildcard pattern that matches everything.
|
||||
of numeric literal patterns can be expressed with two dots, as in `M..N`. The
|
||||
underscore (`_`) is a wildcard pattern that matches everything.
|
||||
|
||||
The patterns in an match arm are followed by a fat arrow, `=>`, then an
|
||||
expression to evaluate. Each case is separated by commas. It's often
|
||||
@ -601,10 +595,9 @@ match my_number {
|
||||
}
|
||||
~~~
|
||||
|
||||
If the arm with the wildcard pattern was left off in the above
|
||||
example, the typechecker would reject it at compile time. `match`
|
||||
constructs must be exhaustive: they must have an arm covering every
|
||||
possible case.
|
||||
`match` constructs must be *exhaustive*: they must have an arm covering every
|
||||
possible case. For example, if the arm with the wildcard pattern was left off
|
||||
in the above example, the typechecker would reject it.
|
||||
|
||||
A powerful application of pattern matching is *destructuring*, where
|
||||
you use the matching to get at the contents of data types. Remember
|
||||
@ -632,11 +625,11 @@ an expression of type `bool` that determines, after the pattern is
|
||||
found to match, whether the arm is taken or not. The variables bound
|
||||
by the pattern are available in this guard expression.
|
||||
|
||||
## Destructuring let
|
||||
## Let
|
||||
|
||||
To a limited extent, it is possible to use destructuring patterns when
|
||||
declaring a variable with `let`. For example, you can say this to
|
||||
extract the fields from a tuple:
|
||||
You've already seen simple `let` bindings. `let` is also a little fancier: it
|
||||
is possible to use destructuring patterns in it. For example, you can say this
|
||||
to extract the fields from a tuple:
|
||||
|
||||
~~~~
|
||||
# fn get_tuple_of_two_ints() -> (int, int) { (1, 1) }
|
||||
@ -646,7 +639,7 @@ let (a, b) = get_tuple_of_two_ints();
|
||||
This will introduce two new variables, `a` and `b`, bound to the
|
||||
content of the tuple.
|
||||
|
||||
You may only use irrefutable patterns—patterns that can never fail to
|
||||
You may only use *irrefutable* patterns—patterns that can never fail to
|
||||
match—in let bindings. Other types of patterns, such as literals, are
|
||||
not allowed.
|
||||
|
||||
@ -736,16 +729,6 @@ fn do_nothing_the_hard_way() -> () { return (); }
|
||||
fn do_nothing_the_easy_way() { }
|
||||
~~~~
|
||||
|
||||
Some functions (such as the C function `exit`) never return normally.
|
||||
In Rust, these are annotated with the pseudo-return type '`!`':
|
||||
|
||||
~~~~
|
||||
fn dead_end() -> ! { fail }
|
||||
~~~~
|
||||
|
||||
Using `!` in your code instead of making up a return type helps the compiler
|
||||
avoid spurious error messages.
|
||||
|
||||
# Basic datatypes
|
||||
|
||||
The core datatypes of Rust are structs, enums (tagged unions, algebraic data
|
||||
|
Loading…
Reference in New Issue
Block a user