Arrays and Slices in Rust

In Rust, an array is a fixed-size collection of values of the same type. A slice is a view into a portion of an array. Arrays are useful when you know the number of elements at compile time, and slices let you work with a section of an array without copying data.

When you need to store multiple values of the same type in Rust, the two main tools are arrays and slices. If you are coming from JavaScript, think of arrays as similar to JS arrays but with a fixed size, and slices as read-only views into a list.

In this post, I will explain how arrays and slices work in Rust, how to use them in your programs, and why Rust separates these two concepts.

Defining Arrays

An array in Rust is defined using square brackets:

let numbers = [1, 2, 3, 4, 5];

All elements must be of the same type. Rust infers the type and length from the literal, or you can be explicit:

let numbers: [i32; 5] = [1, 2, 3, 4, 5];

This defines an array of 5 elements, all of type i32.

Fixed Length

Rust arrays have a fixed size known at compile time. You cannot add or remove elements like you would in a dynamic list. For resizable collections, you will use Vec later on.

You can also create arrays with repeated values:

let zeros = [0; 5]; // same as [0, 0, 0, 0, 0]

Accessing Elements

Access items using their index:

let first = numbers[0];
let last = numbers[4];

Rust will panic at runtime if you access an index out of bounds:

let x = numbers[5]; // will crash the program

Iterating Over Arrays

You can use a loop to process each item:

for num in numbers {
    println!("{}", num);
}

This works because arrays implement the IntoIterator trait.

Array Length

You can get the number of elements with .len():

println!("Length: {}", numbers.len());

Introducing Slices

A slice is a reference to a part of an array. You do not own the data, just a window into it:

let slice = &numbers[1..4]; // elements at index 1, 2, 3

This gives you a slice of type &[i32]. Slices are very useful for writing functions that take flexible input sizes.

You can also slice the full array:

let all = &numbers[..]; // same as &numbers[0..numbers.len()]

Slices in Functions

Here is a function that takes a slice:

fn print_slice(slice: &[i32]) {
    for val in slice {
        println!("{}", val);
    }
}

And you can call it with:

print_slice(&numbers[0..3]);

This is efficient because no data is copied, just a reference is passed.

Example Program

fn main() {
    let values = [10, 20, 30, 40, 50];
    
    let slice = &values[1..4];

    println!("Array length: {}", values.len());
    println!("Second to fourth values:");

    for v in slice {
        println!("{}", v);
    }
}

This program shows how to declare an array, create a slice, and access its values.

Arrays vs. Slices

FeatureArraySlice
OwnershipOwns dataReference to data
SizeFixed at compile timeDynamically sized
Type[T; N]&[T]
MutabilityBased on array itselfBased on borrowed data

Summary

Arrays in Rust are collections of a fixed number of values of the same type. Slices allow you to borrow and work with a subset of an array without copying it. Arrays are fast and memory-safe, and slices give you flexibility when writing functions or processing parts of data.