Copyedit section 3 of tutorial

This commit is contained in:
Tim Chevalier 2012-10-10 19:32:11 -07:00
parent 38ccaed4ce
commit 6627ac6623

View File

@ -184,8 +184,8 @@ and mostly have the same precedence as in C; comments are again like C.
The main surface difference to be aware of is that the condition at The main surface difference to be aware of is that the condition at
the head of control structures like `if` and `while` do not require the head of control structures like `if` and `while` do not require
paretheses, while their bodies *must* be wrapped in parentheses, while their bodies *must* be wrapped in
brackets. Single-statement, bracket-less bodies are not allowed. braces. Single-statement, unbraced bodies are not allowed.
~~~~ ~~~~
# fn recalibrate_universe() -> bool { true } # fn recalibrate_universe() -> bool { true }
@ -200,9 +200,9 @@ fn main() {
} }
~~~~ ~~~~
The `let` keyword introduces a local variable. Variables are immutable The `let` keyword introduces a local variable. Variables are immutable by
by default, so `let mut` can be used to introduce a local variable default. To introduce a local variable that you can re-assign later, use `let
that can be reassigned. mut` instead.
~~~~ ~~~~
let hi = "hi"; let hi = "hi";
@ -224,14 +224,14 @@ let imaginary_size = monster_size * 10.0;
let monster_size: int = 50; let monster_size: int = 50;
~~~~ ~~~~
Local variables may shadow earlier declarations, as in the previous Local variables may shadow earlier declarations, as in the previous example:
example in which `monster_size` is first declared as a `float` `monster_size` was first declared as a `float`, and then then a second
then a second `monster_size` is declared as an int. If you were to actually `monster_size` was declared as an int. If you were to actually compile this
compile this example though, the compiler will see that the second example, though, the compiler will determine that the second `monster_size` is
`monster_size` is unused, assume that you have made a mistake, and issue unused and issue a warning (because this situation is likely to indicate a
a warning. For occasions where unused variables are intentional, their programmer error). For occasions where unused variables are intentional, their
name may be prefixed with an underscore to silence the warning, like name may be prefixed with an underscore to silence the warning, like `let
`let _monster_size = 50;`. _monster_size = 50;`.
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
@ -278,10 +278,10 @@ let price =
}; };
~~~~ ~~~~
Both pieces of code are exactly equivalentthey assign a value to Both pieces of code are exactly equivalent: they assign a value to
`price` depending on the condition that holds. Note that there `price` depending on the condition that holds. Note that there
are not semicolons in the blocks of the second snippet. This is are no semicolons in the blocks of the second snippet. This is
important; the lack of a semicolon after the last statement in a important: the lack of a semicolon after the last statement in a
braced block gives the whole block the value of that last expression. braced block gives the whole block the value of that last expression.
Put another way, the semicolon in Rust *ignores the value of an expression*. Put another way, the semicolon in Rust *ignores the value of an expression*.
@ -290,8 +290,10 @@ would simply assign `()` (nil or void) to `price`. But without the semicolon, ea
branch has a different value, and `price` gets the value of the branch that branch has a different value, and `price` gets the value of the branch that
was taken. was taken.
In short, everything that's not a declaration (`let` for variables, In short, everything that's not a declaration (declarations are `let` for
`fn` for functions, et cetera) is an expression, including function bodies. variables, `fn` for functions, and any top-level named items such as
[traits](#traits), [enum types](#enums), and [constants](#constants)) is an
expression, including function bodies.
~~~~ ~~~~
fn is_four(x: int) -> bool { fn is_four(x: int) -> bool {
@ -314,7 +316,7 @@ something—in which case you'll have embedded it in a bigger statement.
# fn foo() -> bool { true } # fn foo() -> bool { true }
# fn bar() -> bool { true } # fn bar() -> bool { true }
# fn baz() -> bool { true } # fn baz() -> bool { true }
// `let` is not an expression, so it is semi-colon terminated; // `let` is not an expression, so it is semicolon-terminated;
let x = foo(); let x = foo();
// When used in statement position, bracy expressions do not // When used in statement position, bracy expressions do not
@ -346,7 +348,7 @@ This may sound intricate, but it is super-useful and will grow on you.
The basic types include the usual boolean, integral, and floating-point types. The basic types include the usual boolean, integral, and floating-point types.
------------------------- ----------------------------------------------- ------------------------- -----------------------------------------------
`()` Nil, the type that has only a single value `()` Unit, the type that has only a single value
`bool` Boolean type, with values `true` and `false` `bool` Boolean type, with values `true` and `false`
`int`, `uint` Machine-pointer-sized signed and unsigned integers `int`, `uint` Machine-pointer-sized signed and unsigned integers
`i8`, `i16`, `i32`, `i64` Signed integers with a specific size (in bits) `i8`, `i16`, `i32`, `i64` Signed integers with a specific size (in bits)
@ -394,10 +396,15 @@ type MonsterSize = uint;
This will provide a synonym, `MonsterSize`, for unsigned integers. It will not This will provide a synonym, `MonsterSize`, for unsigned integers. It will not
actually create a new, incompatible type—`MonsterSize` and `uint` can be used actually create a new, incompatible type—`MonsterSize` and `uint` can be used
interchangeably, and using one where the other is expected is not a type interchangeably, and using one where the other is expected is not a type
error. error. In that sense, types declared with `type` are *structural*: their
meaning follows from their structure, and their names are irrelevant in the
type system.
To create data types which are not synonyms, `struct` and `enum` Sometimes, you want your data types to be *nominal* instead of structural: you
can be used. They're described in more detail below, but they look like this: want their name to be part of their meaning, so that types with the same
structure but different names are not interchangeable. Rust has two ways to
create nominal data types: `struct` and `enum`. They're described in more
detail below, but they look like this:
~~~~ ~~~~
enum HidingPlaces { enum HidingPlaces {
@ -416,12 +423,12 @@ enum MonsterSize = uint; // a single-variant enum
## Literals ## Literals
Integers can be written in decimal (`144`), hexadecimal (`0x90`), and Integers can be written in decimal (`144`), hexadecimal (`0x90`), or
binary (`0b10010000`) base. Each integral type has a corresponding literal binary (`0b10010000`) base. Each integral type has a corresponding literal
suffix that can be used to indicate the type of a literal: `i` for `int`, suffix that can be used to indicate the type of a literal: `i` for `int`,
`u` for `uint`, and `i8` for the `i8` type, etc. `u` for `uint`, and `i8` for the `i8` type, etc.
In the absense of an integer literal suffix, Rust will infer the In the absence of an integer literal suffix, Rust will infer the
integer type based on type annotations and function signatures in the integer type based on type annotations and function signatures in the
surrounding program. In the absence of any type information at all, surrounding program. In the absence of any type information at all,
Rust will assume that an unsuffixed integer literal has type Rust will assume that an unsuffixed integer literal has type
@ -439,10 +446,10 @@ a suffix, the literal is assumed to be of type `float`. Suffixes `f32`
(32-bit) and `f64` (64-bit) can be used to create literals of a (32-bit) and `f64` (64-bit) can be used to create literals of a
specific type. specific type.
The nil literal is written just like the type: `()`. The keywords The unit literal is written just like the type: `()`. The keywords
`true` and `false` produce the boolean literals. `true` and `false` produce the boolean literals.
Character literals are written between single quotes, as in `'x'`. Just as in Character literals are written between single quotes, as in `'x'`. Just like
C, Rust understands a number of character escapes, using the backslash C, Rust understands a number of character escapes, using the backslash
character, such as `\n`, `\r`, and `\t`. String literals, character, such as `\n`, `\r`, and `\t`. String literals,
written between double quotes, allow the same escape sequences. Rust strings written between double quotes, allow the same escape sequences. Rust strings
@ -450,13 +457,13 @@ may contain newlines.
## Constants ## Constants
Compile-time constants are declared with `const`. All scalar types, Compile-time constants are declared with `const`. A constant may have any
like integers and floats, may be declared `const`, as well as fixed scalar type (for example, integer or float). Other allowable constant types
length vectors, static strings (more on this later), and structs. are fixed-length vectors, static strings (more on this later), and
Constants may be declared in any scope and may refer to other structs. Constants may be declared in any scope and may refer to other
constants. Constant declarations are not type inferred, so must always constants. The compiler does not infer types for constants, so constants must
have a type annotation. By convention they are written in all capital always be declared with a type annotation. By convention, they are written in
letters. all capital letters.
~~~ ~~~
// Scalars can be constants // Scalars can be constants
@ -480,7 +487,7 @@ const MY_STRUCTY_PASSWORD: Password = Password { value: MY_PASSWORD };
Rust's set of operators contains very few surprises. Arithmetic is done with Rust's set of operators contains very few surprises. Arithmetic is done with
`*`, `/`, `%`, `+`, and `-` (multiply, divide, remainder, plus, minus). `-` is `*`, `/`, `%`, `+`, and `-` (multiply, divide, remainder, plus, minus). `-` is
also a unary prefix operator that does negation. As in C, the bit operators also a unary prefix operator that negates numbers. As in C, the bit operators
`>>`, `<<`, `&`, `|`, and `^` are also supported. `>>`, `<<`, `&`, `|`, and `^` are also supported.
Note that, if applied to an integer value, `!` flips all the bits (like `~` in Note that, if applied to an integer value, `!` flips all the bits (like `~` in
@ -502,21 +509,21 @@ assert y == 4u;
~~~~ ~~~~
The main difference with C is that `++` and `--` are missing, and that The main difference with C is that `++` and `--` are missing, and that
the logical bitwise operators have higher precedence in C, `x & 2 > 0` the logical bitwise operators have higher precedence—in C, `x & 2 > 0`
means `x & (2 > 0)`, but in Rust, it means `(x & 2) > 0`, which is means `x & (2 > 0)`, but in Rust, it means `(x & 2) > 0`, which is
more likely what a novice expects. more likely to be what a novice expects.
## Syntax extensions ## Syntax extensions
*Syntax extensions* are special forms that are not built into the language, *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 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 a name refers to a syntax extension, the names of all syntax extensions end
`!`. The standard library defines a few syntax extensions, the most useful of with `!`. The standard library defines a few syntax extensions, the most
which is `fmt!`, a `sprintf`-style text formatter that is expanded at compile useful of which is `fmt!`, a `sprintf`-style text formatter that an early
time. compiler phase expands statically.
`fmt!` supports most of the directives that [printf][pf] supports, but `fmt!` supports most of the directives that [printf][pf] supports, but unlike
will give you a compile-time error when the types of the directives printf, will give you a compile-time error when the types of the directives
don't match the types of the arguments. don't match the types of the arguments.
~~~~ ~~~~
@ -530,8 +537,9 @@ io::println(fmt!("what is this thing: %?", mystery_object));
[pf]: http://en.cppreference.com/w/cpp/io/c/fprintf [pf]: http://en.cppreference.com/w/cpp/io/c/fprintf
You can define your own syntax extensions with the macro system, which is out You can define your own syntax extensions with the macro system. For details, see the [macro tutorial][macros].
of scope of this tutorial.
[macros]: tutorial-macros.html
# Control structures # Control structures