- Views: 1
- Report Article
- Articles
- Writing
- Article Marketing
What Are Enums In Rust?
Posted: Nov 13, 2020
Defining Enums
Enumerations or Enums are custom data types that allow us to define a type by enumerating its possible values.
Example:
IP Addresses:
Version 4 or Version 6
The property of being V4 or V6 at a time make enum structures appropriate, because enum values can only be one of the variants.
But both versions are still IP Addresses and should be treated as the same type.
Code it:
enum IpAddrKind {
V4
V6 Variants
}
Creating Instances:
- allow(unused_variables)]
fn main() {
enum IpAddrKind {
V4,
V6, }
let four = IpAddrKind::V4;
let six = IpAddrKind::V6; }
Defining & Calling a Function:
We can define a function that takes any IpAddrkind and
can call it with either of its variant.
- allow(unused_variables)]
fn main() {
enum IpAddrKind {
V4,
V6,
}
Where’s the Data?
We’ve just learnt how to make Enums and to create instances and defining and calling functions.
But we have not stored any data in last example.
So we can add data using structs and by some other ways..
Adding Data Using Structs:
enum IpAddrKind {
V4,
V6,
}
struct
let home = ;
let loopback = ;
A Concise Way Using an Enum:
Hurray!
We’ve finally used structs to somehow associate values with the
variants.
BUT
We can do the same thing in a more concise way using just an
enum.
Adding Data Using Enums:
This new definition of the IpAddr enum says that both V4
and V6 variants will have associated String values.
enum IpAddr {
V4(String),
V6(String),
}
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));
An Advantage Against Struct:
Each variant can have different types and amounts of
associated data in enums.
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
Standard Library Definition for IpAddr:
As we wanted to store IPaddresses and encode which kind they are is so common
that the standard library has a definition we can use! Let’s look at how the standard library defines IpAddr.
struct Ipv4Addr {
// --snip--
}
struct Ipv6Addr {
// --snip--
}
enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}
Is This A Win For Any Data Type!
Yes! The previous codes shown us that we can put
any kind of data inside an Enum Variant.
We can even include Enums!
Another Example:
A message enum which has a wide variety of types
embedded in its variants.
enum,
Write(String),
ChangeColor(i32, i32, i32),
}
Same Thing Using Structs:
Defining an enum with variants is almost similar to defining different
kinds of struct definitions.
struct QuitMessage; // unit struct
struct
struct WriteMessage(String); // tuple struct
struct ChangeColorMessage(i32, i32, i32); //
tuple struct
So Enums are Easy!
Because if we use different structs which have different types
than we couldn’t as easily define a function to take any of these
kinds of messages as we could with the Message enum which
itself is only single type.
One More Similarity: "Impl Block"
Just as we’re able to define methods on structs using impl, we’re
also able to define methods on enums.
impl Message {
fn call(&self) {
// method body would be defined here
}
}
let m = Message::Write(String::from("hello"));
m.call();
The "Option" Enum:
The "Option" enum is another enum defined by the standard
library. The Option type is used in many places because it
encodes the very common scenario in which a value could be
something or it could be nothing.
Null Feature for Languages:
Null is a value that means there is no value there. In languages with
null, variables can always be in one of two states: null or not-null.
Problem?
The problem with null values is that if you try to use a null
value as a not-null value, you’ll get an error of some kind.
Because this null or not-null property is pervasive, it’s
extremely easy to make this kind of error.
Does Rust have Nulls?
No! However, the concept that null is trying to express is still a
useful one: a null is a value that is currently invalid or absent for
some reason.
So, What does Rust have?
Enum! that can encode the concept of a value being
present or absent. This enum is "Option", and it is
defined in the standard library.
The "Option" Enum Defined by Std. Lib:
The Option enum is so useful that it’s
even included in the prelude; you don’t
need to bring it into scope explicitly. In
addition, so are its variants: you can use
Some and None directly without the
Option:: prefix. The Option enum is still
just a regular enum, and Some(T) and None
are still variants of type Option.
enum Option
{
Some(T),
None,
}}
Example:
Here we’ve an example of using Option values to hold number
types and string types. If we use None rather than Some, we need
to tell Rust what type of Option we have, because the compiler
can’t infer the type that the Some variant will hold by looking only
at a None value.
let some_number = Some(5);
let some_string = Some("a string");
let absent_number: Option = None;
So Why Option is Better than having Null?
Because Option and T (where T can be any type) are different
types, the compiler won’t let us use an Option value as if it were
definitely a valid value. Like a code which is trying to add an i8 to an
Option won’t compile and will give an error because Rust
doesn’t understand how to add an i8 and an Option, because
they’re different types.
let x: i8 = 5;
let y: Option = Some(5);
let sum = x + y;
That’s How We Code Safely and Confidently!
In order to have a value that can possibly be null, we must explicitly
opt in by making the type of that value Option. Everywhere that a
value has a type that isn’t an Option, we can safely assume that
the value isn’t null. That’s how Rust increases the safety of code.
About the Author
Mansoor Ahmed Chemical Engineer,Web developer
Rate this Article
Leave a Comment