From 7bb0cd76f323b6d9f0b5a3347188183ce346c489 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 9 Apr 2015 19:05:49 -0400 Subject: [PATCH] Write the 'primitive types' section of TRPL A brief introduction to each type, with pointers to the primitive pages for more info. --- src/doc/trpl/SUMMARY.md | 5 +- src/doc/trpl/arrays.md | 48 ------ src/doc/trpl/primitive-types.md | 267 +++++++++++++++++++++++++++++++- src/doc/trpl/slices.md | 21 --- src/doc/trpl/tuples.md | 97 ------------ 5 files changed, 267 insertions(+), 171 deletions(-) delete mode 100644 src/doc/trpl/arrays.md delete mode 100644 src/doc/trpl/slices.md delete mode 100644 src/doc/trpl/tuples.md diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index d894e1c47253b..019c8bc00a681 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -17,8 +17,8 @@ * [`Deref` coercions](deref-coercions.md) * [Syntax and Semantics](syntax-and-semantics.md) * [Variable Bindings](variable-bindings.md) - * [Primitive Types](primitive-types.md) * [Functions](functions.md) + * [Primitive Types](primitive-types.md) * [Comments](comments.md) * [Structs](structs.md) * [Mutability](mutability.md) @@ -35,8 +35,6 @@ * [Move semantics](move-semantics.md) * [Drop](drop.md) * [Vectors](vectors.md) - * [Arrays](arrays.md) - * [Slices](slices.md) * [Strings](strings.md) * [Traits](traits.md) * [Operators and Overloading](operators-and-overloading.md) @@ -47,7 +45,6 @@ * [Crates and Modules](crates-and-modules.md) * [`static`](static.md) * [`const`](const.md) - * [Tuples](tuples.md) * [Tuple Structs](tuple-structs.md) * [Attributes](attributes.md) * [Conditional Compilation](conditional-compilation.md) diff --git a/src/doc/trpl/arrays.md b/src/doc/trpl/arrays.md deleted file mode 100644 index a6ecac962d60d..0000000000000 --- a/src/doc/trpl/arrays.md +++ /dev/null @@ -1,48 +0,0 @@ -% Arrays - -Like many programming languages, Rust has list types to represent a sequence of -things. The most basic is the *array*, a fixed-size list of elements of the -same type. By default, arrays are immutable. - -```{rust} -let a = [1, 2, 3]; // a: [i32; 3] -let mut m = [1, 2, 3]; // mut m: [i32; 3] -``` - -There's a shorthand for initializing each element of an array to the same -value. In this example, each element of `a` will be initialized to `0`: - -```{rust} -let a = [0; 20]; // a: [i32; 20] -``` - -Arrays have type `[T; N]`. We'll talk about this `T` notation later, when we -cover generics. - -You can get the number of elements in an array `a` with `a.len()`, and use -`a.iter()` to iterate over them with a for loop. This code will print each -number in order: - -```{rust} -let a = [1, 2, 3]; - -println!("a has {} elements", a.len()); -for e in a.iter() { - println!("{}", e); -} -``` - -You can access a particular element of an array with *subscript notation*: - -```{rust} -let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3] - -println!("The second name is: {}", names[1]); -``` - -Subscripts start at zero, like in most programming languages, so the first name -is `names[0]` and the second name is `names[1]`. The above example prints -`The second name is: Brian`. If you try to use a subscript that is not in the -array, you will get an error: array access is bounds-checked at run-time. Such -errant access is the source of many bugs in other systems programming -languages. diff --git a/src/doc/trpl/primitive-types.md b/src/doc/trpl/primitive-types.md index 2878e7ce4754e..fcbe2b2f8bf70 100644 --- a/src/doc/trpl/primitive-types.md +++ b/src/doc/trpl/primitive-types.md @@ -1,3 +1,268 @@ % Primitive Types -Coming Soon! +The Rust language has a number of types that are considered ‘primitive’. This +means that they’re built-in to the language. Rust is structured in such a way +that the standard library also provides a number of useful types built on top +of these ones, as well, but these are the most primitive. + +# Booleans + +Rust has a built in boolean type, named `bool`. It has two values, `true` and `false`: + +```rust +let x = true; + +let y: bool = false; +``` + +A common use of booleans is in [`if` statements][if]. + +[if]: if.html + +You can find more documentation for `bool`s [in the standard library +documentation][bool]. + +[bool]: ../std/primitive.bool.html + +# `char` + +The `char` type represents a single Unicode scalar value. You can create `char`s +with a single tick: (`'`) + +```rust +let x = 'x'; +let two_hearts = '💕'; +``` + +Unlike some other languages, this means that Rust’s `char` is not a single byte, +but four. + +You can find more documentation for `char`s [in the standard library +documentation][char]. + +[char]: ../std/primitive.char.html + +# Numeric types + +Rust has a variety of numeric types in a few categories: signed and unsigned, +fixed and variable, floating-point and integer. + +These types consist of two parts: the category, and the size. For example, +`u16` is an unsigned type with sixteen bits of size. More bits lets you have +bigger numbers. + +If a number literal has nothing to cause its type to be inferred, it defaults: + +```rust +let x = 42; // x has type i32 + +let y = 1.0; // y has type f64 +``` + +Here’s a list of the different numeric types, with links to their documentation +in the standard library: + +* [i16](../std/primitive.i16.html) +* [i32](../std/primitive.i32.html) +* [i64](../std/primitive.i64.html) +* [i8](../std/primitive.i8.html) +* [u16](../std/primitive.u16.html) +* [u32](../std/primitive.u32.html) +* [u64](../std/primitive.u64.html) +* [u8](../std/primitive.u8.html) +* [isize](../std/primitive.isize.html) +* [usize](../std/primitive.usize.html) +* [f32](../std/primitive.f32.html) +* [f64](../std/primitive.f64.html) + +Let’s go over them by category: + +## Signed and Unsigned + +Integer types come in two varieties: signed and unsigned. To understand the +difference, let’s consider a number with four bits of size. A signed, four-bit +number would let you store numbers from `-8` to `+7`. Signed numbers use +‘two’s compliment representation’. An unsigned four bit number, since it does +not need to store negatives, can store values from `0` to `+15`. + +Unsigned types use a `u` for their category, and signed types use `i`. The `i` +is for ‘integer’. So `u8` is an eight-bit unsigned number, and `i8` is an +eight-bit signed number. + +## Fixed size types + +Fixed size types have a specific number of bits in their representation. Valid +bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer, +and `i64` is a signed, 64-bit integer. + +## Variable sized types + +Rust also provides types whose size depends on the size of a pointer of the +underlying machine. These types have ‘size’ as the category, and come in signed +and unsigned varieties. This makes for two types: `isize` and `usize`. + +## Floating-point types + +Rust also two floating point types: `f32` and `f64`. These correspond to +IEEE-754 single and double precision numbers. + +# Arrays + +Like many programming languages, Rust has list types to represent a sequence of +things. The most basic is the *array*, a fixed-size list of elements of the +same type. By default, arrays are immutable. + +```rust +let a = [1, 2, 3]; // a: [i32; 3] +let mut m = [1, 2, 3]; // m: [i32; 3] +``` + +Arrays have type `[T; N]`. We’ll talk about this `T` notation [in the generics +section][generics]. The `N` is a compile-time constant, for the length of the +array. + +There’s a shorthand for initializing each element of an array to the same +value. In this example, each element of `a` will be initialized to `0`: + +```rust +let a = [0; 20]; // a: [i32; 20] +``` + +You can get the number of elements in an array `a` with `a.len()`: + +```rust +let a = [1, 2, 3]; + +println!("a has {} elements", a.len()); +``` + +You can access a particular element of an array with *subscript notation*: + +```rust +let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3] + +println!("The second name is: {}", names[1]); +``` + +Subscripts start at zero, like in most programming languages, so the first name +is `names[0]` and the second name is `names[1]`. The above example prints +`The second name is: Brian`. If you try to use a subscript that is not in the +array, you will get an error: array access is bounds-checked at run-time. Such +errant access is the source of many bugs in other systems programming +languages. + +You can find more documentation for `array`s [in the standard library +documentation][array]. + +[array]: ../std/primitive.array.html + +# Slices + +A ‘slice’ is a reference to (or “view” into) another data structure. They are +useful for allowing safe, efficient access to a portion of an array without +copying. For example, you might want to reference just one line of a file read +into memory. By nature, a slice is not created directly, but from an existing +variable. Slices have a length, can be mutable or not, and in many ways behave +like arrays: + +```rust +let a = [0, 1, 2, 3, 4]; +let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 +``` + +Slices have type `&[T]`. We’ll talk about that `T` when we cover +[generics][generics]. + +[generics]: generics.html + +You can find more documentation for `slices`s [in the standard library +documentation][slice]. + +[slice]: ../std/primitive.slice.html + +# `str` + +Rust’s `str` type is the most primitive string type. As an [unsized type][dst], +it’s not very useful by itself, but becomes useful when placed behind a reference, +like [`&str`][strings]. As such, we’ll just leave it at that. + +[dst]: unsized-types.html +[strings]: strings.html + +You can find more documentation for `str` [in the standard library +documentation][str]. + +[str]: ../std/primitive.str.html + +# Tuples + +A tuple is an ordered list of fixed size. Like this: + +```rust +let x = (1, "hello"); +``` + +The parentheses and commas form this two-length tuple. Here’s the same code, but +with the type annotated: + +```rust +let x: (i32, &str) = (1, "hello"); +``` + +As you can see, the type of a tuple looks just like the tuple, but with each +position having a type name rather than the value. Careful readers will also +note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple. +In systems programming languages, strings are a bit more complex than in other +languages. For now, just read `&str` as a *string slice*, and we’ll learn more +soon. + +You can access the fields in a tuple through a *destructuring let*. Here’s +an example: + +```rust +let (x, y, z) = (1, 2, 3); + +println!("x is {}", x); +``` + +Remember [before][let] when I said the left-hand side of a `let` statement was more +powerful than just assigning a binding? Here we are. We can put a pattern on +the left-hand side of the `let`, and if it matches up to the right-hand side, +we can assign multiple bindings at once. In this case, `let` "destructures," +or "breaks up," the tuple, and assigns the bits to three bindings. + +[let]: variable-bindings.html + +This pattern is very powerful, and we’ll see it repeated more later. + +There are also a few things you can do with a tuple as a whole, without +destructuring. You can assign one tuple into another, if they have the same +contained types and [arity]. Tuples have the same arity when they have the same +length. + +[arity]: glossary.html#arity + +```rust +let mut x = (1, 2); // x: (i32, i32) +let y = (2, 3); // y: (i32, i32) + +x = y; +``` + +You can find more documentation for tuples [in the standard library +documentation][tuple]. + +[tuple]: ../std/primitive.tuple.html + +# Functions + +Functions also have a type! They look like this: + +``` +fn foo(x: i32) -> i32 { x } + +let x: fn(i32) -> i32 = foo; +``` + +In this case, `x` is a ‘function pointer’ to a function that takes an `i32` and +returns an `i32`. diff --git a/src/doc/trpl/slices.md b/src/doc/trpl/slices.md deleted file mode 100644 index a31c0ac3c4e69..0000000000000 --- a/src/doc/trpl/slices.md +++ /dev/null @@ -1,21 +0,0 @@ -% Slices - -A *slice* is a reference to (or "view" into) an array. They are useful for -allowing safe, efficient access to a portion of an array without copying. For -example, you might want to reference just one line of a file read into memory. -By nature, a slice is not created directly, but from an existing variable. -Slices have a length, can be mutable or not, and in many ways behave like -arrays: - -```{rust} -let a = [0, 1, 2, 3, 4]; -let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 - -for e in middle.iter() { - println!("{}", e); // Prints 1, 2, 3 -} -``` - -You can also take a slice of a vector, `String`, or `&str`, because they are -backed by arrays. Slices have type `&[T]`, which we'll talk about when we cover -generics. diff --git a/src/doc/trpl/tuples.md b/src/doc/trpl/tuples.md deleted file mode 100644 index dd526d05b671e..0000000000000 --- a/src/doc/trpl/tuples.md +++ /dev/null @@ -1,97 +0,0 @@ -% Tuples - -The first compound data type we're going to talk about is called the *tuple*. -A tuple is an ordered list of fixed size. Like this: - -```rust -let x = (1, "hello"); -``` - -The parentheses and commas form this two-length tuple. Here's the same code, but -with the type annotated: - -```rust -let x: (i32, &str) = (1, "hello"); -``` - -As you can see, the type of a tuple looks just like the tuple, but with each -position having a type name rather than the value. Careful readers will also -note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple. -You have briefly seen `&str` used as a type before, and we'll discuss the -details of strings later. In systems programming languages, strings are a bit -more complex than in other languages. For now, just read `&str` as a *string -slice*, and we'll learn more soon. - -You can access the fields in a tuple through a *destructuring let*. Here's -an example: - -```rust -let (x, y, z) = (1, 2, 3); - -println!("x is {}", x); -``` - -Remember before when I said the left-hand side of a `let` statement was more -powerful than just assigning a binding? Here we are. We can put a pattern on -the left-hand side of the `let`, and if it matches up to the right-hand side, -we can assign multiple bindings at once. In this case, `let` "destructures," -or "breaks up," the tuple, and assigns the bits to three bindings. - -This pattern is very powerful, and we'll see it repeated more later. - -There are also a few things you can do with a tuple as a whole, without -destructuring. You can assign one tuple into another, if they have the same -contained types and [arity]. Tuples have the same arity when they have the same -length. - -```rust -let mut x = (1, 2); // x: (i32, i32) -let y = (2, 3); // y: (i32, i32) - -x = y; -``` - -You can also check for equality with `==`. Again, this will only compile if the -tuples have the same type. - -```rust -let x = (1, 2, 3); -let y = (2, 2, 4); - -if x == y { - println!("yes"); -} else { - println!("no"); -} -``` - -This will print `no`, because some of the values aren't equal. - -Note that the order of the values is considered when checking for equality, -so the following example will also print `no`. - -```rust -let x = (1, 2, 3); -let y = (2, 1, 3); - -if x == y { - println!("yes"); -} else { - println!("no"); -} -``` - -One other use of tuples is to return multiple values from a function: - -```rust -fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) } - -fn main() { - let (x, y) = next_two(5); - println!("x, y = {}, {}", x, y); -} -``` - -Even though Rust functions can only return one value, a tuple *is* one value, -that happens to be made up of more than one value. You can also see in this -example how you can destructure a pattern returned by a function, as well.