Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!
:timing
:sccache 1Tips & Traps¶
Summary of Collections in Rust has a good summary on when to each which collection in Rust.
The length of an array is considered part of its type and thus has to be defined at compile time. You cannot define a dynamic sized array.
Vecis essentially dynamic sized array.An array is copyable if its element type is copyable. This has a pitfall of implicity copy if you are not careful! For example, if you iterate an array using
into_iterand then use the array again, a copy of the array will be made forinto_iterwhich is likely NOT what you want.:::rust let arr = [1, 2, 3]; for v in arr.into_iter() { println!("{}", v); } for v in arr.into_iter() { println!("{}", v); }You have to be very careful about arrays when you work with them.
Arrays of sizes from 0 to 32 (inclusive) implement the Default trait if the element type allows it. As a stopgap, trait implementations are statically generated up to size 32. This will be improved once const generics is leveraged to implement arrays.
The function from_fn provides an easy way to construct multi-elements arrays. The Rust crate array-macro provides a macro
array!to easily construct multi-elements arrays.
Array vs Vec in Rust¶
Array is fixed size and allocated on a stack while Vec has a dynamic size and is allocated on the heap. Array is slightly faster than Vec (since stack is faster than heap) especially when the size of the sequence is small. Multi-dimensional array is even faster than Vec of Vec due to improved caching.
An array can’t be empty at any time. When you crate an array, you immediately have to initialize it. In practice, you might have to initialize it twice, once with a zero/default value, and second time with some computed one.
A Vec is not copyable even if its element type is copyable, so you won’t worry about copying a Vec accidentally. However, an array is copyable if its element type is copyable! This means that array has a pitfall of implicity copy if you are not careful! For example, if you iterate an array using
into_iterand then use the array again, a copy of the array will be made forinto_iterwhich is likely NOT what you want.:::rust let arr = [1, 2, 3]; for v in arr.into_iter() { println!("{}", v); } for v in arr.into_iter() { println!("{}", v); }You have to be very careful about arrays when you work with them.
:sccache 1sccache: true
use std::vec::Vec;let arr = [1, 2, 3];
for v in arr {
println!("{}", v);
}
for v in arr {
println!("{}", v);
}1
2
3
1
2
3
()fn print_type_of<T>(_: &T) {
println!("{}", std::any::type_name::<T>())
}Construct Arrays¶
struct Foo;
let arr: [Option<Foo>; 100] = Default::default();let arr: [Option<Foo>; 100] = Default::default();
^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[Option<Foo>; 100]`
the trait bound `[Option<Foo>; 100]: Default` is not satisfied
help: the following other types implement trait `Default`:
&[T]
&mut [T]
[T; 0]
[T; 10]
[T; 11]
[T; 12]
[T; 13]
[T; 14]
and 27 others(Integer) Array of Zeros¶
let arr: [i32; 5] = [0; 5];
arr[0, 0, 0, 0, 0]let arr2 = &[0; 5];
arr2[0, 0, 0, 0, 0]print_type_of(arr2)[i32; 5]
()Construct More Complicated Arrays¶
use array_macro::array;let arr: [usize; 5] = std::array::from_fn(|i| i);
arr[0, 1, 2, 3, 4]static arr2: [usize; 5] = std::array::from_fn(|i| i);
arr2[E0015] Error: cannot call non-const fn `std::array::from_fn::<usize, 5, [closure@src/lib.rs:2:47: 2:50]>` in statics
╭─[command_7:1:1]
│
1 │ static arr2: [usize; 5] = std::array::from_fn(|i| i);
· ─────────────┬────────────
· ╰────────────── error: cannot call non-const fn `std::array::from_fn::<usize, 5, [closure@src/lib.rs:2:47: 2:50]>` in statics
───╯let arr: [Vec<usize>; 2] = {
let v = vec![
vec![1, 2, 3],
vec![4, 5, 6],
];
std::array::from_fn(|i| v[i].clone())
};
arr[[1, 2, 3], [4, 5, 6]]let v = ["apples", "cake", "coffee"];
for text in v {
println!("I like {}.", text);
}I like apples.
I like cake.
I like coffee.
()let v = ["apples".to_string(), "cake".to_string(), "coffee".to_string()];
for text in &v {
println!("I like {}.", text);
}I like apples.
I like cake.
I like coffee.
()The size of the array must be determined at compile time.
let n = 5;
n5let arr2: [i32; n] = [0; n];
arrlet arr2: [i32; n] = [0; n];
^ non-constant value
attempt to use a non-constant value in a constant
help: consider using `const` instead of `let`
const nlet arr2: [i32; n] = [0; n];
^ non-constant value
attempt to use a non-constant value in a constant
help: consider using `const` instead of `let`
const nlet numbers = [0, 1, 2, 3];
numbers[0, 1, 2, 3]numbers[0]0numbers[3]3for i in 1..3 {
println!("{}", numbers[i])
}1
2
()capacity¶
An array does not have the method capacity since it is of fixed length.
numbers.capacity()numbers.capacity()
^^^^^^^^ method not found in `[i32; 4]`
no method named `capacity` found for array `[i32; 4]` in the current scopelen¶
numbers.len()4push¶
numbers.push(4)numbers.push(4)
^^^^ method not found in `[i32; 4]`
no method named `push` found for array `[i32; 4]` in the current scopeSize (in Bytes) of Array¶
std::mem::size_of_val(&numbers)16Iterate Through an Array¶
for loop / into_iter¶
let array: [i32; 3] = [0; 3];
for x in array {
println!("{}", x);
}0
0
0
()let words = vec!["alpha", "beta", "gamma"];
let merged: String = words.into_iter().collect();
println!("{}", merged);alphabetagamma
let words = ["alpha", "beta", "gamma"];
let merged: String = words.into_iter().collect();
println!("{}", merged);let merged: String = words.into_iter().collect();
^^^^^^^ value of type `String` cannot be built from `std::iter::Iterator<Item=&&str>`
a value of type `String` cannot be built from an iterator over elements of type `&&str`
help: the trait `FromIterator<&&str>` is not implemented for `String`array.into_iter().map(|&i| array[i as usize]).sum::<i32>()0array.iter().map(|&i| array[i as usize]).sum::<i32>()0Using Array Index¶
for i in 0..5 {
println!("{}", numbers[i]);
}0
1
2
3
4
()Using the .iter() Method¶
Technically speaking,
an array is coerced to a slice (implicitly) before calling .iter().
for n in numbers.iter() {
println!("{}", n);
}0
1
2
3
4
()Using the .iter_mut Method¶
This is similar to the .iter() method but allows you to update the array while iterate through it.
let mut numbers: [i32; 5] = [0, 1, 2, 3, 4];
for n in numbers.iter_mut() {
*n *= 2;
}
println!("{:?}", numbers);[0, 2, 4, 6, 8]
()Iterator¶
map
collect
group_by
2-D Array¶
let mut state = [[0u8; 4]; 6];
state[0][1] = 42;state[[0, 42, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]Array vs Slice¶
An array is a collection of objects of the same type T,
stored in contiguous memory.
Arrays are created using brackets [],
and their length,
which is known at compile time,
is part of their type signature [T; length].
Slices are similar to arrays, but their length is not known at compile time. Instead, a slice is a two-word object, the first word is a pointer to the data, and the second word is the length of the slice. The word size is the same as usize, determined by the processor architecture eg 64 bits on an x86-64. Slices can be used to borrow a section of an array, and have the type signature &[T].