mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-27 06:14:55 +00:00
Rollup merge of #24253 - steveklabnik:doc_primitive_types, r=alexcrichton
A brief introduction to each type, with pointers to the primitive pages for more info.
This commit is contained in:
commit
dbbedb5a8b
@ -17,8 +17,8 @@
|
|||||||
* [`Deref` coercions](deref-coercions.md)
|
* [`Deref` coercions](deref-coercions.md)
|
||||||
* [Syntax and Semantics](syntax-and-semantics.md)
|
* [Syntax and Semantics](syntax-and-semantics.md)
|
||||||
* [Variable Bindings](variable-bindings.md)
|
* [Variable Bindings](variable-bindings.md)
|
||||||
* [Primitive Types](primitive-types.md)
|
|
||||||
* [Functions](functions.md)
|
* [Functions](functions.md)
|
||||||
|
* [Primitive Types](primitive-types.md)
|
||||||
* [Comments](comments.md)
|
* [Comments](comments.md)
|
||||||
* [Structs](structs.md)
|
* [Structs](structs.md)
|
||||||
* [Mutability](mutability.md)
|
* [Mutability](mutability.md)
|
||||||
@ -35,8 +35,6 @@
|
|||||||
* [Move semantics](move-semantics.md)
|
* [Move semantics](move-semantics.md)
|
||||||
* [Drop](drop.md)
|
* [Drop](drop.md)
|
||||||
* [Vectors](vectors.md)
|
* [Vectors](vectors.md)
|
||||||
* [Arrays](arrays.md)
|
|
||||||
* [Slices](slices.md)
|
|
||||||
* [Strings](strings.md)
|
* [Strings](strings.md)
|
||||||
* [Traits](traits.md)
|
* [Traits](traits.md)
|
||||||
* [Operators and Overloading](operators-and-overloading.md)
|
* [Operators and Overloading](operators-and-overloading.md)
|
||||||
@ -47,7 +45,6 @@
|
|||||||
* [Crates and Modules](crates-and-modules.md)
|
* [Crates and Modules](crates-and-modules.md)
|
||||||
* [`static`](static.md)
|
* [`static`](static.md)
|
||||||
* [`const`](const.md)
|
* [`const`](const.md)
|
||||||
* [Tuples](tuples.md)
|
|
||||||
* [Tuple Structs](tuple-structs.md)
|
* [Tuple Structs](tuple-structs.md)
|
||||||
* [Attributes](attributes.md)
|
* [Attributes](attributes.md)
|
||||||
* [Conditional Compilation](conditional-compilation.md)
|
* [Conditional Compilation](conditional-compilation.md)
|
||||||
|
@ -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.
|
|
@ -1,3 +1,268 @@
|
|||||||
% Primitive Types
|
% 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`.
|
||||||
|
@ -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.
|
|
@ -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.
|
|
Loading…
Reference in New Issue
Block a user