Introduction
In this lab, we will be exploring structures in the Rust programming language. There are three types of structures ("structs") that can be created using the struct keyword: tuple structs, classic C structs, and unit structs. Tuple structs are essentially named tuples, C structs are the traditional structs found in C programming, and unit structs are field-less and useful for generics. We can define structs with multiple fields, such as Person which has name and age fields. Structs can also be reused as fields of another struct, as shown in the example of a Rectangle which consists of two Point structs representing the top left and bottom right corners. We can initialize structs using field init shorthand and access their fields using dot notation. It is also possible to destructure structs using the let binding. Additionally, the lab provides two activities - creating a function rect_area to calculate the area of a Rectangle using nested destructuring, and creating a function square that takes a Point and a f32 as arguments and returns a Rectangle with its top left corner on the point and a width and height corresponding to the f32.
Note: If the lab does not specify a file name, you can use any file name you want. For example, you can use
main.rs, compile and run it withrustc main.rs && ./main.
Structures
There are three types of structures ("structs") that can be created using the struct keyword:
- Tuple structs, which are, basically, named tuples.
- The classic C structs
- Unit structs, which are field-less, are useful for generics.
// An attribute to hide warnings for unused code.
#![allow(dead_code)]
#[derive(Debug)]
struct Person {
name: String,
age: u8,
}
// A unit struct
struct Unit;
// A tuple struct
struct Pair(i32, f32);
// A struct with two fields
struct Point {
x: f32,
y: f32,
}
// Structs can be reused as fields of another struct
struct Rectangle {
// A rectangle can be specified by where the top left and bottom right
// corners are in space.
top_left: Point,
bottom_right: Point,
}
fn main() {
// Create struct with field init shorthand
let name = String::from("Peter");
let age = 27;
let peter = Person { name, age };
// Print debug struct
println!("{:?}", peter);
// Instantiate a `Point`
let point: Point = Point { x: 10.3, y: 0.4 };
// Access the fields of the point
println!("point coordinates: ({}, {})", point.x, point.y);
// Make a new point by using struct update syntax to use the fields of our
// other one
let bottom_right = Point { x: 5.2, ..point };
// `bottom_right.y` will be the same as `point.y` because we used that field
// from `point`
println!("second point: ({}, {})", bottom_right.x, bottom_right.y);
// Destructure the point using a `let` binding
let Point { x: left_edge, y: top_edge } = point;
let _rectangle = Rectangle {
// struct instantiation is an expression too
top_left: Point { x: left_edge, y: top_edge },
bottom_right: bottom_right,
};
// Instantiate a unit struct
let _unit = Unit;
// Instantiate a tuple struct
let pair = Pair(1, 0.1);
// Access the fields of a tuple struct
println!("pair contains {:?} and {:?}", pair.0, pair.1);
// Destructure a tuple struct
let Pair(integer, decimal) = pair;
println!("pair contains {:?} and {:?}", integer, decimal);
}
Activity
- Add a function
rect_areawhich calculates the area of aRectangle(try using nested destructuring). - Add a function
squarewhich takes aPointand af32as arguments, and returns aRectanglewith its top left corner on the point, and a width and height corresponding to thef32.
Summary
Congratulations! You have completed the Structures lab. You can practice more labs in LabEx to improve your skills.