|
1 | 1 | % Primitive Types
|
2 | 2 |
|
3 |
| -Coming Soon! |
| 3 | +The Rust language has a number of types that are considered ‘primitive’. This |
| 4 | +means that they’re built-in to the language. Rust is structured in such a way |
| 5 | +that the standard library also provides a number of useful types built on top |
| 6 | +of these ones, as well, but these are the most primitive. |
| 7 | + |
| 8 | +# Booleans |
| 9 | + |
| 10 | +Rust has a built in boolean type, named `bool`. It has two values, `true` and `false`: |
| 11 | + |
| 12 | +```rust |
| 13 | +let x = true; |
| 14 | + |
| 15 | +let y: bool = false; |
| 16 | +``` |
| 17 | + |
| 18 | +A common use of booleans is in [`if` statements][if]. |
| 19 | + |
| 20 | +[if]: if.html |
| 21 | + |
| 22 | +You can find more documentation for `bool`s [in the standard library |
| 23 | +documentation][bool]. |
| 24 | + |
| 25 | +[bool]: ../std/primitive.bool.html |
| 26 | + |
| 27 | +# `char` |
| 28 | + |
| 29 | +The `char` type represents a single Unicode scalar value. You can create `char`s |
| 30 | +with a single tick: (`'`) |
| 31 | + |
| 32 | +```rust |
| 33 | +let x = 'x'; |
| 34 | +let two_hearts = '💕'; |
| 35 | +``` |
| 36 | + |
| 37 | +Unlike some other languages, this means that Rust’s `char` is not a single byte, |
| 38 | +but four. |
| 39 | + |
| 40 | +You can find more documentation for `char`s [in the standard library |
| 41 | +documentation][char]. |
| 42 | + |
| 43 | +[char]: ../std/primitive.char.html |
| 44 | + |
| 45 | +# Numeric types |
| 46 | + |
| 47 | +Rust has a variety of numeric types in a few categories: signed and unsigned, |
| 48 | +fixed and variable, floating-point and integer. |
| 49 | + |
| 50 | +These types consist of two parts: the category, and the size. For example, |
| 51 | +`u16` is an unsigned type with sixteen bits of size. More bits lets you have |
| 52 | +bigger numbers. |
| 53 | + |
| 54 | +If a number literal has nothing to cause its type to be inferred, it defaults: |
| 55 | + |
| 56 | +```rust |
| 57 | +let x = 42; // x has type i32 |
| 58 | + |
| 59 | +let y = 1.0; // y has type f64 |
| 60 | +``` |
| 61 | + |
| 62 | +Here’s a list of the different numeric types, with links to their documentation |
| 63 | +in the standard library: |
| 64 | + |
| 65 | +* [i16](../std/primitive.i16.html) |
| 66 | +* [i32](../std/primitive.i32.html) |
| 67 | +* [i64](../std/primitive.i64.html) |
| 68 | +* [i8](../std/primitive.i8.html) |
| 69 | +* [u16](../std/primitive.u16.html) |
| 70 | +* [u32](../std/primitive.u32.html) |
| 71 | +* [u64](../std/primitive.u64.html) |
| 72 | +* [u8](../std/primitive.u8.html) |
| 73 | +* [isize](../std/primitive.isize.html) |
| 74 | +* [usize](../std/primitive.usize.html) |
| 75 | +* [f32](../std/primitive.f32.html) |
| 76 | +* [f64](../std/primitive.f64.html) |
| 77 | + |
| 78 | +Let’s go over them by category: |
| 79 | + |
| 80 | +## Signed and Unsigned |
| 81 | + |
| 82 | +Integer types come in two varieties: signed and unsigned. To understand the |
| 83 | +difference, let’s consider a number with four bits of size. A signed, four-bit |
| 84 | +number would let you store numbers from `-8` to `+7`. Signed numbers use |
| 85 | +‘two’s compliment representation’. An unsigned four bit number, since it does |
| 86 | +not need to store negatives, can store values from `0` to `+15`. |
| 87 | + |
| 88 | +Unsigned types use a `u` for their category, and signed types use `i`. The `i` |
| 89 | +is for ‘integer’. So `u8` is an eight-bit unsigned number, and `i8` is an |
| 90 | +eight-bit signed number. |
| 91 | + |
| 92 | +## Fixed size types |
| 93 | + |
| 94 | +Fixed size types have a specific number of bits in their representation. Valid |
| 95 | +bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer, |
| 96 | +and `i64` is a signed, 64-bit integer. |
| 97 | + |
| 98 | +## Variable sized types |
| 99 | + |
| 100 | +Rust also provides types whose size depends on the size of a pointer of the |
| 101 | +underlying machine. These types have ‘size’ as the category, and come in signed |
| 102 | +and unsigned varieties. This makes for two types: `isize` and `usize`. |
| 103 | + |
| 104 | +## Floating-point types |
| 105 | + |
| 106 | +Rust also two floating point types: `f32` and `f64`. These correspond to |
| 107 | +IEEE-754 single and double precision numbers. |
| 108 | + |
| 109 | +# Arrays |
| 110 | + |
| 111 | +Like many programming languages, Rust has list types to represent a sequence of |
| 112 | +things. The most basic is the *array*, a fixed-size list of elements of the |
| 113 | +same type. By default, arrays are immutable. |
| 114 | + |
| 115 | +```rust |
| 116 | +let a = [1, 2, 3]; // a: [i32; 3] |
| 117 | +let mut m = [1, 2, 3]; // m: [i32; 3] |
| 118 | +``` |
| 119 | + |
| 120 | +Arrays have type `[T; N]`. We’ll talk about this `T` notation [in the generics |
| 121 | +section][generics]. The `N` is a compile-time constant, for the length of the |
| 122 | +array. |
| 123 | + |
| 124 | +There’s a shorthand for initializing each element of an array to the same |
| 125 | +value. In this example, each element of `a` will be initialized to `0`: |
| 126 | + |
| 127 | +```rust |
| 128 | +let a = [0; 20]; // a: [i32; 20] |
| 129 | +``` |
| 130 | + |
| 131 | +You can get the number of elements in an array `a` with `a.len()`: |
| 132 | + |
| 133 | +```rust |
| 134 | +let a = [1, 2, 3]; |
| 135 | + |
| 136 | +println!("a has {} elements", a.len()); |
| 137 | +``` |
| 138 | + |
| 139 | +You can access a particular element of an array with *subscript notation*: |
| 140 | + |
| 141 | +```rust |
| 142 | +let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3] |
| 143 | + |
| 144 | +println!("The second name is: {}", names[1]); |
| 145 | +``` |
| 146 | + |
| 147 | +Subscripts start at zero, like in most programming languages, so the first name |
| 148 | +is `names[0]` and the second name is `names[1]`. The above example prints |
| 149 | +`The second name is: Brian`. If you try to use a subscript that is not in the |
| 150 | +array, you will get an error: array access is bounds-checked at run-time. Such |
| 151 | +errant access is the source of many bugs in other systems programming |
| 152 | +languages. |
| 153 | + |
| 154 | +You can find more documentation for `array`s [in the standard library |
| 155 | +documentation][array]. |
| 156 | + |
| 157 | +[array]: ../std/primitive.array.html |
| 158 | + |
| 159 | +# Slices |
| 160 | + |
| 161 | +A ‘slice’ is a reference to (or “view” into) another data structure. They are |
| 162 | +useful for allowing safe, efficient access to a portion of an array without |
| 163 | +copying. For example, you might want to reference just one line of a file read |
| 164 | +into memory. By nature, a slice is not created directly, but from an existing |
| 165 | +variable. Slices have a length, can be mutable or not, and in many ways behave |
| 166 | +like arrays: |
| 167 | + |
| 168 | +```rust |
| 169 | +let a = [0, 1, 2, 3, 4]; |
| 170 | +let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 |
| 171 | +``` |
| 172 | + |
| 173 | +Slices have type `&[T]`. We’ll talk about that `T` when we cover |
| 174 | +[generics][generics]. |
| 175 | + |
| 176 | +[generics]: generics.html |
| 177 | + |
| 178 | +You can find more documentation for `slices`s [in the standard library |
| 179 | +documentation][slice]. |
| 180 | + |
| 181 | +[slice]: ../std/primitive.slice.html |
| 182 | + |
| 183 | +# `str` |
| 184 | + |
| 185 | +Rust’s `str` type is the most primitive string type. As an [unsized type][dst], |
| 186 | +it’s not very useful by itself, but becomes useful when placed behind a reference, |
| 187 | +like [`&str`][strings]. As such, we’ll just leave it at that. |
| 188 | + |
| 189 | +[dst]: unsized-types.html |
| 190 | +[strings]: strings.html |
| 191 | + |
| 192 | +You can find more documentation for `str` [in the standard library |
| 193 | +documentation][str]. |
| 194 | + |
| 195 | +[str]: ../std/primitive.str.html |
| 196 | + |
| 197 | +# Tuples |
| 198 | + |
| 199 | +A tuple is an ordered list of fixed size. Like this: |
| 200 | + |
| 201 | +```rust |
| 202 | +let x = (1, "hello"); |
| 203 | +``` |
| 204 | + |
| 205 | +The parentheses and commas form this two-length tuple. Here’s the same code, but |
| 206 | +with the type annotated: |
| 207 | + |
| 208 | +```rust |
| 209 | +let x: (i32, &str) = (1, "hello"); |
| 210 | +``` |
| 211 | + |
| 212 | +As you can see, the type of a tuple looks just like the tuple, but with each |
| 213 | +position having a type name rather than the value. Careful readers will also |
| 214 | +note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple. |
| 215 | +In systems programming languages, strings are a bit more complex than in other |
| 216 | +languages. For now, just read `&str` as a *string slice*, and we’ll learn more |
| 217 | +soon. |
| 218 | + |
| 219 | +You can access the fields in a tuple through a *destructuring let*. Here’s |
| 220 | +an example: |
| 221 | + |
| 222 | +```rust |
| 223 | +let (x, y, z) = (1, 2, 3); |
| 224 | + |
| 225 | +println!("x is {}", x); |
| 226 | +``` |
| 227 | + |
| 228 | +Remember [before][let] when I said the left-hand side of a `let` statement was more |
| 229 | +powerful than just assigning a binding? Here we are. We can put a pattern on |
| 230 | +the left-hand side of the `let`, and if it matches up to the right-hand side, |
| 231 | +we can assign multiple bindings at once. In this case, `let` "destructures," |
| 232 | +or "breaks up," the tuple, and assigns the bits to three bindings. |
| 233 | + |
| 234 | +[let]: variable-bindings.html |
| 235 | + |
| 236 | +This pattern is very powerful, and we’ll see it repeated more later. |
| 237 | + |
| 238 | +There are also a few things you can do with a tuple as a whole, without |
| 239 | +destructuring. You can assign one tuple into another, if they have the same |
| 240 | +contained types and [arity]. Tuples have the same arity when they have the same |
| 241 | +length. |
| 242 | + |
| 243 | +[arity]: glossary.html#arity |
| 244 | + |
| 245 | +```rust |
| 246 | +let mut x = (1, 2); // x: (i32, i32) |
| 247 | +let y = (2, 3); // y: (i32, i32) |
| 248 | + |
| 249 | +x = y; |
| 250 | +``` |
| 251 | + |
| 252 | +You can find more documentation for tuples [in the standard library |
| 253 | +documentation][tuple]. |
| 254 | + |
| 255 | +[tuple]: ../std/primitive.tuple.html |
| 256 | + |
| 257 | +# Functions |
| 258 | + |
| 259 | +Functions also have a type! They look like this: |
| 260 | + |
| 261 | +``` |
| 262 | +fn foo(x: i32) -> i32 { x } |
| 263 | +
|
| 264 | +let x: fn(i32) -> i32 = foo; |
| 265 | +``` |
| 266 | + |
| 267 | +In this case, `x` is a ‘function pointer’ to a function that takes an `i32` and |
| 268 | +returns an `i32`. |
0 commit comments