Rust by examples notes about primitives.
Primitives
Rust provides access to a wide variety of primitives
.
scalar Types
- signed integers:
i8
,i16
,i32
,i64
andisize
(pointer size) - unsigned integers:
u8
,u16
,u32
,u64
andusize
(pointer size) - floating point: f32, f64
char
Unicode scalar values like'a'
,'α'
and'∞'
(4 bytes each)bool
eithertrue
andfalse
- and the unit type
()
, whose only possible value is an empty tuple:()
note: Despite the value of a unit type being a tuple, it is not considered a compound type because it does not contain multiple values.
Compound Types
- arrys like [1, 2, 3]
- tuples like (1, true)
Tuples
A tuple is a collection of values of different types. Tuples are constructed using parenthese ()
, and each tuple itself is a value with type signature (T1, T2, ...)
, where T1
, T2
are the types of its members.Functions can use tuples to return multiple values, as tuples can hold any number of values.
1 |
|
Values can be extracted from the tuple using tuple indexing,such aslong_tuple.0
,long_tuple.1
Tuples can be tuple members
1 | let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16); |
let
can be used to bind the members of a tuple to variables.
1 | let tuple = (1, true, 1.2); |
Display for tuples
1 | use std::fmt::{Display, Formatter, Result}; |
output
1 | Matrix: |
Arrays and Slices
An array is a collection of objects of the same type T
, stored in contiguous memory. Arrays are created using brackets []
, and their size, which is know at compile time, is part of their signature [T; size]
.
Slices are similar to arrays, but their size is not know at compile time. Instead, a slice is a two-word object, the first word is a pointer to the data, the second word is the length of the slice. The word size is the same as usize, determined by archiecture eg 64 bits on x86-64.Slices can be used to borrow a section of an array, and have type signature &[T]
.
elements can be initalized to the same value
1 | let x: [i32; 500] = [0; 500] |
Custom Types
Rust custom data types are formed mainly through the two keywords:
struct
: define a structureenum
: define an enumeration
Structures
There are three types of structures (“struct”) that can be created using the struct
keyword:
- Tuple structs, which are, basically, named tuples.
1 | struct Pair(i32, i32); |
- The classic
C structs
.1
2
3
4
5
6
7struct Point {
x: f32,
y: f32,
}
let point = Point { 1, 1.1};
// Destructure the point using a `let` binding
let Point { x: my_x, y: my_y } = point; - Unit structs, which are field-less, are useful for generics.
1 | struct Nil; |
Note: Structs can be reused as fields of another struct.
rectangle struct example
1 | struct Point { |
output
1 | 0.5 |
Enums
The enum
keyword allows the creation of a type which may be one of a few different variants. Any variant which is valid as a struct
is also valid as enum
.
example
1 | // Create an `enum` to classify a web event. Note how both |
use
The use
declaration can be used so manual scoping isn’t needed:
1 | enum Status { |
no use
1 | let status = Status::A; |
use
1 | use crate::Status::{A, B}; |
C-like
enum
can also be used as C-like enums.
1 | // An attribute to hide warnings for unused code. |
Linked-list
Cons: Tuple struct that wraps an element and a pointer to the next node
1 | use crate::List::*; |
constants
Rust has two different types of constants which can be declared in any scope including global. Both require explicit type annotation:
const
: An unchanged value (the common case).static
: A possibly mutable variable with'static
lifetime. The staic lifetime is inferred and does not have to be specified. Accessing or modifying a mutable static variable isunsafe
.
Type conversation
The generic conversations will use the From
and Into
traits.
From
and Into
From
and Into
traits are inherently linked. If your are able to convert type A from type B, then it should be easy to believe that we should be able to convert type B to type A.
The From
trait allows for a type to define how to create itself from another type, hence providing a very simple mechanism for converting between several types.
1 | let my_str = "hi"; |
The Into
trait is simply the reciprocal of the From
trait. That is, if you have implemented the From
trait for your type you get the Into
implementation for free.
1 | use std::convert::From; |
To and from Strings
Converting to String
To convert any type to String
is as simple as implenting the ToString
trait for the type. Rather than doing so directly, you should implement the fmt::Display
trait which automagically provides ToString
and also allows printing the types as discussed in the section on print!
.
Parsing a String
1 | fn main() { |