Vectors

Dear Computer

Chapter 10: Everything Revisited

Vectors

An array cannot change size, but a Vec may. Vectors are structs that live on the heap and are growable like ArrayList in Java. We create an empty Vec with the new associated function:

Rust
let mut names: Vec<&str> = Vec::new();

Since the list is empty, the compiler cannot infer the type and an explicit type is needed in the declaration. We could leave off the type if a later operation indicates the type, as this push call does:

Rust
let mut names = Vec::new();
names.push("Meg Murry");

We can also add a generic type parameter to the new call:

Rust
let mut names = Vec::<&str>::new();

In Java, we would have written the type as Vec<&str>, not Vec::<&str>. In Rust, when a generic type is referenced outside of the typename slot of a declaration, we need an extra :: between the type name and the generic parameter. Without this extra ::, the Rust grammar has an ambiguity. The < could be either a less-than relational operator or the delimiter of the generic parameter. The ::<> is affectionately called the turbofish operator because it looks like a speedy fish.

If we want to initialize the vector with certain values, we use the vec! macro with an initialization list:

Rust
let mut names = vec!["Meg", "Charles Wallace", "Calvin"];

The Vec type supports operations similar to ArrayList.

Summary

Rust is a young language that incorporates good ideas from many different languages. Thanks to its static type system, the compiler is able to identify problems and generate fast machine code that asks few questions at runtime. Immutability is the default, reducing the wariness that we necessarily feel when sharing data. Conditionals and some loops are expressions, so we can write computational pipelines like we would in a functional language. The enum command provides a type algebra for declaring variants with tuple or record fields. When we don't need variants, we can use plain tuples or structs. Pattern matching is legal in parameter lists, loops, and conditionals, which means we don't need to muddy our code with field accesses. We may define behaviors for any type and call them in the receiver.method syntax we expect from object-oriented languages. There's a rich standard library with abstractions like String and Vec.

← ArraysLecture: Rust Mains →