Options and variants
Options and variants are types that have one or more non-overlapping cases. An option or variant is always exactly one of these cases; they cannot be undefined or more than one case.
Options
Options are a particular kind of variants that have two cases: None and Some. When the option is Some, it carries some value that you define.
You can use options to allow for a null or empty value. For example, an ordinary integer variable must always have a value, but an option that contains an integer (defined as the type sp.option[sp.int]) can be either None to indicate a null value or sp.Some(n) to indicate a value, where n is any integer.
SmartPy uses options to catch errors and undefined cases. For example, dividing two numbers with the sp.ediv function results in an option. If the division operation is valid, the result is Some containing the quotient and remainder. However, if you try to divide by zero, the result is None.
You can define the value of an option as any other type.
Reading options requires you to handle both cases. You can use functions to get the value of an option or use pattern matching, as described in Matching over options and variants. For example, the functions is_none and is_some return true if the option is None or Some, respectively. If you are confident that an option is Some, you can get the value with the function unwrap_some, which raises an exception if the option is None, as in this example:
value_opt = sp.Some(5)
sp.cast(value_opt, sp.option[sp.int])
is_some = value_opt.is_some() # true
is_none = value_opt.is_none() # false
value_integer = value_opt.unwrap_some() # 5- x.is_none() → sp.bool
Checks whether the given value is
None. For exampleNone.is_none() == Trueandsp.Some(42).is_none() == False.
- x.is_some() → sp.bool
Checks whether the given value is of the form
sp.Some(...). For exampleNone.is_some() == Falseandsp.Some(42).is_some() == True.
- x.unwrap_some([error=exception: t]) → t
Extracts the argument of an option value if it is of the form
sp.Some(...). Raises an exception (that can be specified aserror) ifx == None. Iferroris specified, the parameter must be named.For example,
sp.Some(42).unwrap_some() == 42, whereasNone.unwrap_some(error="oops")raises the exception"oops".
Variants
Variants in SmartPy are enumerations of cases, where each case comes with a value. Variants are similar to features such as enums, sum types, and tagged/disjoint unions in other languages.
Variants are like options, but you can define any number of cases for them instead of only None and Some. Each case can contain different types.
For example, sp.variant(Circle=sp.int, Rectangle=sp.pair[sp.int, sp.int]) is a variant type with two cases. Its values are sp.variant.Circle(r) (for any r of type sp.int) and sp.variant.Rectangle(h, w) (for any h and w of type sp.int).
- x.is_variant.V() → sp.bool
Checks whether a value is of the given variant
V, for example:smartpyc = sp.variant.Circle(2) assert c.is_variant.Circle()
- x.unwrap.V([error=exception: t]) → t
Obtains the argument of a given variant
V. Raises an error if it is of a different variant. Iferroris specified, the parameter must be named. For example:smartpyc = sp.variant.Circle(2) assert c.unwrap.Circle() == 2 r = c.unwrap.Rectangle() # raises an exception r = c.unwrap.Rectangle(error="Err") # raises "Err"
Matching over options and variants
To match over options and variants, you can use the pattern-matching syntax (match <expr>). The following example creates a variant and uses the match keyword to branch based on its contents:
v = sp.variant.Circle(2)
match v:
case Circle(radius):
assert radius == 2
case Rectangle(dimensions):
...
# Do something with `dimensions.h` and `dimensions.w`.The syntax for matching options is similar; they have two cases with the Some case providing a value, as in this example:
o = sp.Some(5)
match o:
case Some(value):
assert value == 5
case None:
...INFO
In SmartPy you can use pattern matching with the match keyword only for options and variants, not for any type as in standard Python.