Compound Types

In Perl, we essentially have just three types: scalar, array, and hash. Each of these is indicated by its sigil.

my $scalar = 3;

my @array = (1, 2, 3);

my %hash = (alpha => 1, beta => 2, gamma => 3);

They are so flexible, though, that we accomplish enormous amounts of work with just these three things. This flexibility comes from the dynamic nature of Perl. A scalar holds a single value. An array holds a list of scalars. A hash holds a list of key-value pairs. There are no other restrictions.

my $scalar = "\N{TOP HAT}";

my @array = (1, "2", ['5', "banana", 3]);

my %hash = (alpha => 1, beta => \@array, gamma => $scalar);

The static nature of Rust means compound data types are more restricted. The Rust compiler needs to know the type of everything.

Arrays

Arrays in Rust are fixed length sequences of things that are all the same type.


#![allow(unused_variables)]
fn main() {
let array: [i32; 3] = [1, 2, 3];
}

What? That's not at all like an array in Perl! In truth, we don't often use arrays directly in Rust either; we more often access them through slices. This is similar to accessing Strings with &str.

You might have an occasion to use a Rust array while programming some time, but in the mean time just ignore the name similarity.

Vectors

When you think you need a Perl array, you probably need a Rust vector.


#![allow(unused_variables)]
fn main() {
let vector = vec![1, 2, 3];
}

These hold lists of things that are all of the same type too, but we can add and remove things from them much as we do in Perl.

my @array = (1, 2, 3);
push @array, 4;

#![allow(unused_variables)]
fn main() {
let mut vector = vec![1, 2, 3];
vector.push(4);
}

In Rust, everything is immutable by default, so we must explicitly declare a vector to be mutable if we wish to change it (e.g., push onto it).

Tuples

Rust's vectors have to be all the same type, though. If you need a list of things of different type, you might need a Rust tuple. These can't change size or change types, but they can hold something akin to a given Perl list.

my @array = (1, '2', "banana");

#![allow(unused_variables)]
fn main() {
let tuple = (1, '2', "banana");
}

This tuple has type (i32, char, &str). It's not comparable to tuples of other lengths or even to other triples of different component types.

HashMaps

When we need something like a Perl hash in Rust, we usually want a HashMap. We must pick a type for our keys and a type for our values, but other than that they are similar to use.

my %hash;
$hash{alpha} = 1;
$hash{beta} = 2;
$hash{gamma} = 3;

#![allow(unused_variables)]
fn main() {
let mut hash = HashMap::new();
hash.insert("alpha", 1);
hash.insert("beta", 2);
hash.insert("gamma", 3);
}

There are other data structures in Rust's std::collections which me might choose for things that we would probably just use a hash for in Perl. For example, in Perl we might use an existence hash (where we only care about the keys and the values are always 1), whereas in Rust we might choose a HashSet.