Records vs Tuples
Mun supports two types of structures: record structs and tuple structs.
A record struct
definition specifies both the name and type of each piece of data, allowing you to retrieve the field by name.
For example, Listing 4-1 shows a record struct
that stores a 2-dimensional vector.
pub struct Vector2 {
x: f32,
y: f32,
}
In contrast, tuple struct
definitions omit field names; only specifying the field types.
Using a tuple struct
makes sense when you want to associate a name with a tuple or distinguish it from other tuples' types, but naming each field would be redundant.
Listing 4-2 depicts a tuple struct
that stores a 3-dimensional vector.
pub struct Vector3(f32, f32, f32)
Create a Struct Instance
To use a record struct
, we create an instance of that struct by stating the name of the struct
and then add curly braces containing key: value
pairs for each of its fields.
The keys have to correspond to the field names in the struct
definition, but can be provided in any order.
Let's create an instance of our Vector2
, as illustrated in Listing 4-3.
pub struct Vector2 {
x: f32,
y: f32,
}
let xy = Vector2 {
x: 1.0,
y: -1.0,
};
To create an instance of a tuple struct
, you only need to state the name of the struct
and specify a comma-separated list of values between round brackets - as shown in Listing 4-4.
As values are not linked to field names, they have to appear in the order specified by the struct
definition.
pub struct Vector3(f32, f32, f32)
let xyz = Vector3(-1.0, 0.0, 1.0);
Field Init Shorthand
It often makes sense to name function variables the same as the fields of a record struct
.
Instead of having to repeat the x
and y
field names, the field init shorthand syntax demonstrated in Listing 4-5 allows you to avoid repetition.
pub struct Vector2 {
x: f32,
y: f32,
}
pub fn vector2_new(x: f32, y: f32) -> Vector2 {
Vector2 { x, y }
}
Access Struct Fields
To access a record's fields, we use the dot notation: vector.x
.
The dot notation can be used both to retrieve and to assign a value to the record's field, as shown in Listing 4-6.
As you can see, the record's name is used to indicate that the function expects two Vector2
instances as function arguments and returns a Vector2
instance as result.
pub struct Vector2 {
x: f32,
y: f32,
}
pub fn vector2_add(lhs: Vector2, rhs: Vector2) -> Vector2 {
lhs.x += rhs.x;
lhs.y += rhs.y;
lhs
}
A tuple struct
doesn't have field names, but instead accesses fields using indices - starting from zero - corresponding to a field's position within the struct definition (see Listing 4-7).
pub struct Vector3(f32, f32, f32)
pub fn vector3_add(lhs: Vector3, rhs: Vector3) -> Vector3 {
lhs.0 += rhs.0;
lhs.1 += rhs.1;
lhs.2 += rhs.2;
lhs
}
Unit Struct
Sometimes it can be useful to define a struct
without any fields.
These so-called unit structs are defined using the struct
keyword and a name, as shown in Listing 4-8.
pub struct Unit;