Rust Arrays Tutorial

In this Rust tutorial we learn about a data container that can hold multiple values instead of just one, the array.

We learn how to initialize an array with values, how to access array elements with the indexer and with a loop, how to mutate array elements and how to pass an array to a function.

What is an array

An array is a data container that can hold multiple separate values of the same type. We can think of it as a variable that can accept multiple separate values.

An array will be allocated to memory sequentially, that’s to say it will occupy memory blocks one after the other. This typically speeds up access to memory.

How to create (initialize) an array

Rust provides us with 3 variations in syntax to declare an array.

Syntax: declare an array
// variation 1
let variable_name = [value_1, value_2, ...];

// variation 2
let variable_name:[data_type; array_size] = [value_1, value_2, ...];

// variation 3
let variable_name:[data_type; array_size] = [default_value_for_all_elements; array_size];

The simplest variation will let the compiler infer the array type from the values we give it.

Example: automatically infer array type
fn main() {

    let users = ["John", "Jane", "Jack", "Jill"];

}

The example above creates an array with 4 string elements.

The second variation allows us to specify the data type and array size explicitly.

To do this we add a colon after the array name, followed by open and close square brackets. Inside the square brackets we specify first the data type, then an integer value for the amount of values the array can hold. The type and size is separated by a semicolon, not a comma.

Example: explicitly declare type and size
fn main() {

    let users:[&str; 4] = ["John", "Jane", "Jack", "Jill"];

}

In the example above, we explicitly declare a data type of string and an array size of 4.

The third variation allows us to initialize all the array elements with the same value.

To do this we add only a single value that will be used to populate all the elements in the array, followed by the array size, and separated with a semicolon.

Example: initialize all array elements with a single value
fn main() {

    let users:[&str; 4] = ["Unknown"; 4];

}

In the example above, all 4 elements in the array will have the value “Unknown”.

How to access array elements with the indexer

Before we proceed, let’s see how to print the whole array to the console.

Example: print the full array to the console
fn main() {

    let users = ["John", "Jane", "Jack", "Jill"];

    println!("{:?}", users);

}

We simply specify the array name in the println macro. The :? between the curly braces will do what’s known as a pretty print variation, allowing us to see the whole array at once.

This helps us quickly see all the values in an array.

Individual array elements are accessed with the indexer. Every element in an array has a corresponding number assigned to it.

0123
JohnJaneJackJill

If we want to access a value, we use its index number between square brackets to get the value.

Example: access individual array elements
fn main() {

    let users = ["John", "Jane", "Jack", "Jill"];

    println!("{}", users[2]);

}

In the example above, we access an element of the array with its corresponding index number.

You may have noticed that we use the number 2, but the value we accessed was “Jack” which is the third element in the array.

Any array or collection with an index, will always start at the number 0, not at 1. This is true for almost all programming languages (lua tables start at 1 for example).

So, if we want to access an element, we just subtract one from its position and we have the correct index.

How to access array elements in a loop

A more practical and effective method to access elements in an array is to loop over them.

Example: loop over all array elements
fn main() {

    let users = ["John", "Jane", "Jack", "Jill"];

    for x in users.iter() {
        println!("User: {}", x);
    }

}

.iter() is a function that we can use to iterate over individual elements. All arrays have access to this function and we use it by simply appending .iter() to the array name.

In the for loop, the temporary variable (in this case x) is used to access each individual element.

How to change array element values

To change elements in an array we have two options.

  • Make the array mutable with mut.
  • Initialize the array anew with the changed values.

Let’s start with a mutable array. We add the mut keyword to the array initialization to allow the array to be mutable.

Then, we assign a new value to the array element by using its index.

Example: mut array
fn main() {

    let mut users = ["John", "Jane", "Jack", "Jill"];

    println!("Before: {}", users[0]);

    // mutate array element 0
    users[0] = "John Doe";

    println!("After: {}", users[0]);

}

The second option is to simply reinitialize the array with different values. This may not be practical in most circumstances but we have the option.

Example: reinitialize array
fn main() {

    let users = ["John", "Jane", "Jack", "Jill"];
    println!("Before: {:?}", users);

    let users = ["John Doe", "Jane Doe", "Jack", "Jill"];
    println!("After: {:?}", users);

}

This solution is not practical because we’ll often want to mutate only a single value in a large array.

How to pass an array to a function

To pass an array to a function as a parameter, we simply declare the parameter as an array.

When declaring an array as a parameter we have to include it’s type and size.

Example: pass an array to a function
fn main() {

    let num:[i32; 2] = [5, 3];

    println!("{:?}", sum(num));
}

fn sum(arr:[i32; 2]) -> i32 {

    return arr[0] + arr[1];

}

In the function definition above, the arr parameter can accept an array of type i32 with 2 elements.

Summary: Points to remember

  • An array is a data container that can hold more than one value.
    • An array is stored sequentially in memory.
    • An array can only accept a single type of values.
  • An array is initialized with values in one of three syntax variations.
    • We can let the compiler infer the type from the values automatically.
  • We access individual array elements with the indexer, specifying their corresponding index number between brackets.
  • For loops are perfect to iterate over elements in an array.
  • To be able to change array element values, we make an array mutable with the mut keyword.
    • To change the value itself, we assign a new value to the element in the array via the indexer.
  • We can pass an array to a function by declaring the parameter as an array. We also have to declare the type and size explicitly.