[Move 2024] Enums #15653
Labels
design
devx
move
Type: Major Feature
Major new functionality or integration, which has a significant impact on the network
Enumerations (or enums) allow programmers to define a single type that contains different shapes of data (or “variants”). A new syntax for declaring enums in Move and pattern matching on enum values will be introduced to the source language, and support for enums will be added to the bytecode and VM. This document will only look at the source syntax and usage of enums and not discuss the lower-level details.
See the main issue for more on Move 2024 changes
For example if we wanted an enum that allowed us to represent the current temperature in Fahrenheit, Celsius, or if the current temperature is unknown we could do so with the following enum
We could then write a function to tell is if the temperature is at or above boiling point using the new pattern-matching functionalities that will be introduced at the same time
Defining Enums
Move enums are made up of zero or more variants. Each variant can either contain no data (such as the
Temperature::Unknown
variant above), or additional data in variant fields. These fields can either be named (like thetemp
field in theTemperature::Celsius
variant), or positional (like theTemperature::Fahrenheit
variant). Enum variants, just like struct fields are private to the module in which the enum is declared.Move enums can be generic and have abilities just like structs in Move. However, enums cannot have the
key
ability because there is no way of defining a commonid: UID
amongst the different variants of the enum. One important implication of this is that enums cannot be objects (but they can be stored in objects).In the Move 2024 release, Move enums will not support recursive fields, but we intend on supporting them in the future. The following is an example of an enum that would not be allowed currently, but would in the future:
Some more examples of what enum declarations in Move will look like and will be allowed:
Referencing and Constructing Enum Values
Variants are always referenced through the enum that defines them, although the type of the enum can be aliased. The following are all valid ways of referencing variants inside the
Temperature
enum above:We do not allow using specific variants, opening enums, or renaming variants. So the following would all be invalid
You can create enum values using one of the enums variants in a similar way to the way you would create struct values
Pattern Matching
We also plan on introducing basic pattern matching to allow easily working with and destructuring enum values. Pattern matches consist of a sequence of match statements. Each match statement has a left-hand-side consisting of a pattern an optional guard and a right-hand side. Pattern matching proceeds from the top-down, and matches the first statement that matches the value.
A pattern can consist of literals (e.g.,
0
,true
), references to enum variants or structs (e.g.,Temperature::Fahrenheit
orSomeStruct
, bindings (e.g.,x
,y
), wildcards_
, and or-patternspattern | pattern
(note: bindings must be the same across or-patterns).Bindings in a pattern match anything in that (structural) position, and are bound both in the optional guard expression, and on the right hand side.
The guard is an expression that returns a boolean, it will be executed only if the pattern matches and before the right hand side is run. If it returns
false
the right-hand side will not be run, and other match statements below it will be checked to see if the value being pattern matched matches any of them.To see some examples:
Note that the wild cards in the
match
expressions above only work because we are taking theTemperature
by value, and therefore we can drop the reference. If we however took theTemperature
by value, and used a wildcard like the following:It would result in an error because
Temperature
does not have thedrop
ability. The two ways to solve this would be to either:drop
ability to theTemperature
type:public enum Temperature has drop { ... }
; orWe additionally have pattern exhaustivity which means that we will ensure that the all possible variants of data are considered. Note however, that in the presence of guard expressions, that you will be required to provide a “default” case like in the above definition of
is_temperature_boiling
. Because of this it’s generally encouraged to not use guard expressions unless it will simplify the match expression, as you will not be notified of an error if you later-on add a new variant to the enum and forget to extend the pattern match.More Examples
As another example you can write a simple Reverse Polish calculator using enums and pattern-matching:
The text was updated successfully, but these errors were encountered: