Option
Option
is a type that represents an optional value which may or may not exist. The concept of Option
in Move is borrowed from Rust, and it is a very useful primitive in Move. Option
is defined in the
Standard Library, and is defined as follows:
// File: move-stdlib/source/option.move
/// Abstraction of a value that may or may not be present.
struct Option<Element> has copy, drop, store {
vec: vector<Element>
}
The 'std::option' module is implicitly imported in every module, so you don't need to add an explicit import.
The Option
type is a generic type with an Element
type parameter. It contains a single field, vec
,
which is a vector
of Element
. The vector can have a length of 0 or 1, representing the
absence or presence of a value, respectively.
The Option
type has two variants: Some
and None
. The Some
variant contains a value, while the None
variant
represents the absence of a value. The Option
type is used to represent the absence of a value in
a type-safe way, avoiding the need for empty or undefined
values.
In Practice
To showcase why the Option
type is necessary, let's look at an example. Consider an application which
takes a user input and stores it in a variable. Some fields are required, and some are optional. For
example, a user's middle name is optional. While we could use an empty string to represent the
absence of a middle name, it would require extra checks to differentiate between an empty string and
a missing middle name. Instead, we can use the Option
type to represent the middle name.
module book::user_registry;
use std::string::String;
/// A struct representing a user record.
public struct User has drop {
first_name: String,
middle_name: Option<String>,
last_name: String,
}
/// Create a new `User` struct with the given fields.
public fun register(
first_name: String,
middle_name: Option<String>,
last_name: String,
): User {
User { first_name, middle_name, last_name }
}
In the previous example, the middle_name
field is of type Option<String>
. This means that the middle_name
field can either contain a String value, wrapped in Some, or be explicitly empty, represented by None. Using
the Option
type makes the optional nature of the field clear, avoiding ambiguity and the need for extra
checks to differentiate between an empty string and a missing middle name.
Using Option
The Option
type, along with the std::option
module, is implicitly imported in Move. This means you can use
the Option
type directly without needing a use
statement. You can then create an Option
value
using the Some
or None
methods.
// `option::some` creates an `Option` value with a value.
let mut opt = option::some(b"Alice");
// `option.is_some()` returns true if option contains a value.
assert!(opt.is_some());
// internal value can be `borrow`ed and `borrow_mut`ed.
assert!(opt.borrow() == &b"Alice");
// `option.extract` takes the value out of the option, leaving the option empty.
let inner = opt.extract();
// `option.is_none()` returns true if option is None.
assert!(opt.is_none());