Enums (or enumerations) is a user-defined data type that allows us to select a value from a list of related values.
In Rust, we use the enum
keyword to create an enum. For example,
enum Sport {
Basketball,
Volleyball,
Football,
Cricket,
}
Here, we have created an enum named Sport
with a list of values Basketball
, Volleyball
, Football
and Cricket
. These enum values are known as variants.
When to use Enum in Rust
Let's look at a situation where we want to define an enum.
Suppose you are creating a program where you have to store a list of directions, and we know that there will be only four possible values for directions: North, East, West, and South.
In this case, we can use an enum where each variant will be the direction.
enum Direction {
North,
East,
South,
West,
}
Now we can access each of the enum variants whenever we have to use a direction in our program.
Note: By convention, we use the Pascal case for enum names and values. In Pascal case, we write the first letter of the word(s) in uppercase.
Accessing Enum Variants in Rust
To access enum values, we first have to create enum instances. For example,
enum Direction {
North,
East
South,
West,
}
Now let's create instances of each enum variant:
let north = Direction::North;
let east = Direction::East;
let south = Direction::South;
let west = Direction::West;
Here, Direction::North
represents the enum variant North
of the Direction
enum, and we are assigning it to the variable north.
Similarly, Direction::East
, Direction::South
and Direction::West
represent variants East
, South
, and West
.
Rust Enum Data Type
Now let's see one example of how enum works in Rust.
fn main() {
// define enum Direction
#[derive(Debug)]
enum Direction {
North,
East,
South,
West,
}
// initialize and access enum variants
let north = Direction::North;
let east = Direction::East;
let south = Direction::South;
let west = Direction::West;
// print enum values
println!("{:?}", north);
println!("{:?}", east);
println!("{:?}", south);
println!("{:?}", west);
}
Output
North East South West
Here, we have created enum instances:
- north - to access enum variant
Direction::North
- east - to access enum variant
Direction::East
- south - to access enum variant
Direction::South
- west - to access enum variant
Direction::West
We have then printed these instances.
Note: We have used #[derive(Debug)]
above the enum definition. It's because this allows Rust to print the variants inside the enum.
Example: Enum Data Type in Rust
Let's see one more example.
fn main() {
// define enum color
#[derive(Debug)]
enum Color {
Green,
Yellow,
Red,
}
// initialize and access enum variants
let green = Color::Green;
let yellow = Color::Yellow;
let red = Color::Red;
// print enum values
println!("{:?}", green);
println!("{:?}", yellow);
println!("{:?}", red);
}
Output
Green Yellow Red
Initializing Enum Variants with Values in Rust
In Rust, we can also initialize enum variants by assigning individual values. For example,
fn main() {
// define enum
#[derive(Debug)]
enum Result {
Score(f64),
Valid(bool),
}
// initialize enum with values
let num = Result::Score(3.14);
let bool = Result::Valid(true);
println!("num = {:?}", num);
println!("bool = {:?}", bool);
}
Output
num = Score(3.14) bool = Valid(true)
In the above example, we have created an enum named Result
with two variants: Score
(f64 type) and Valid
(boolean type).
Notice the statements to create enum instances.
let num = Result::Score(3.14);
let bool = Result::Valid(true);
Here, we are initializing the enum variants with values inside the bracket. That is,
Result::Score(3.14)
- initialize theScore
variant with the value3.14
Result::Valid(true)
- initialize theValid
variant with the valuetrue
Enum with different Data Types in Rust
In Rust, we can also create enums where the enum variants are of different data types: struct, tuple, string, etc.
1. Enum with a struct variant
enum Game {
Quit,
Position { x: i32, y: i32 },
}
Here the Game
enum has an anonymous struct Position { x: i32, y: i32 }
as a variant.
2. Enum with a tuple variant
enum Game {
Quit,
ChangeBackground(i32, i32, i32),
}
Here, the Game
enum has a tuple ChangeBackground(i32, i32, i32)
as a variant.
3. Enum with a string variant
enum Game {
Quit,
Print(String),
}
Here, the Game
enum has a Print(String)
variant.
Example: Enum Variants of Different Data Types
Earlier, we see that enum variants can be of different data types. We can even create an enum where each variant is of a different type. That is one variant will be a string, another one will be a struct and so on. For example,
enum Game {
Quit,
Print(String),
Position { x: i32, y: i32 },
ChangeBackground(i32, i32, i32),
}
This enum has four different types of variants:
Quit
has no data associated with it at allPrint
includes a singleString
Position
includes an anonymous struct inside itChangeBackground
includes threei32
values (tuple)
Let's look at an example of how we can use this enum,
fn main() {
// define enum with multiple variants and data types
#[derive(Debug)]
enum Game {
Quit,
Print(String),
Position { x: i32, y: i32 },
ChangeBackground(i32, i32, i32),
}
// initialize enum with values
let quit = Game::Quit;
let print = Game::Print(String::from("Hello World!"));
let position = Game::Position { x: 10, y: 20 };
let color = Game::ChangeBackground(200, 255, 255);
// print enum values
println!("quit = {:?}", quit);
println!("print = {:?}", print);
println!("position = {:?}", position);
println!("color = {:?}", color);
}
Here, we initialize the enum with values according to the enum definition.
Let's look at the Position
variant from the Game
enum,
enum Game {
..
Position { x: i32, y: i32 }
..
}
Now, to assign a value, we target the variant Position
and initialize it with values in the same format as the enum definition.
let position = Game::Position { x: 10, y: 20 };
Here, we initialize the struct variant Position
with x: 10
and y: 20
.
Similarly, we have assigned values to all the other variants and printed it on the screen.
let quit = Game::Quit;
let print = Game::Print(String::from("Hello World!"));
let color = Game::ChangeBackground(200, 255, 255);
Mutable Enum in Rust
To create a mutable enum, we can use the mut
keyword while initializing the enum.
Suppose we have an enum,
// enum definition
enum Animal {
Dog(String, f64),
Cat(String, f64),
}
// create mutable enum variant
let mut dog = Animal::Dog("Tucker", 37.4);
Example: Mutable Enum
fn main() {
// define enum with multiple variants and data types
#[derive(Debug)]
enum Animal {
Dog(String, f64),
Cat(String, f64),
}
// initialize a mutable enum variant with values
let mut dog = Animal::Dog(String::from("Tucker"), 37.4);
// initialize a non-mutable enum variant with values
let cat = Animal::Cat(String::from("Maya"), 22.3);
// print enum values before change
println!("dog before = {:?}", dog);
println!("cat before = {:?}", cat);
// change the value of mutable enum variant
dog = Animal::Dog(String::from("Sterling"), 21.1);
// print enum values after change
println!();
println!("dog after = {:?}", dog);
println!("cat after = {:?}", cat);
}
Output
dog before = Dog("Tucker", 37.4) cat before = Cat("Maya", 22.3) dog after = Dog("Sterling", 21.1) cat after = Cat("Maya", 22.3)
Here, we have initialized an enum variant and assigned it to a variable dog using the mut
keyword.
let mut dog = Animal::Dog(String::from("Tucker"), 37.4);
This allows us to change the value of the dog variable. In the program above, we change the dog variable to,
dog = Animal::Dog(String::from("Sterling"), 21.1);
As a result, the value of the variable dog changes from Dog("Tucker", 37.4)
to Dog("Sterling", 21.1)
.