Sum types
The sum type is a special data type that can hold a value of one of several types while maintaining type safety.
Suppose you need to describe the width of an element in CSS. It can be specified either as a number of pixels or as a string expression. Of course, the CSS specification is more complex, but we will simplify it for the sake of the example.
To specify the sum type, use the type
keyword:
The |
lists the types that the sum type will consist of.
Now let us try to use it:
To create a new instance of the sum type, use type casting:
In this case, the expression that is cast to the sum type must be one of the
types listed through |
when declaring the sum type.
Otherwise, there will be a compilation error.
Recursive sum types
The sum type can be recursive, i.e. refer to itself, but only if it is defined as an array or map element type:
Accessing fields from structures in the sum type
If the sum type contains structures, then through the sum type you can access their fields if a field with the same name exists in all structures that are part of the sum type.
Calling methods from structures in sum type
Unlike fields, even if all structures in a sum type have a method with the same name, they cannot be accessed through the sum type!
Get the type of the stored value
Sometimes you need to find out what type is stored in an instance of the sum type.
To do this, for any sum type, the type_name()
method is defined, which returns
the name of the type that is currently stored.
Working with sum type
To conveniently handle the type of the sum, the match
expression can be
used to check the type of the stored value.
At the same time, match
must be exhaustive, that is, handle all possible
variants of the sum type or have an else
branch:
With sum types, you could build recursive structures:
is
and as
operators
The is
operator checks if the value stored in the sum type is of the specified type:
The as
operator casts the value stored in the sum type to the specified type:
If the value stored in the sum type is not of the specified type, then the program will panic.
Because of this, the as
operator should be used with caution.
Smart casts can be used as a replacement.
Smart casts
The V compiler can automatically type cast inside if
and match
blocks:
In this example, width
is of type int
within the body of the if
block.
The compiler understands that inside the if
block, the width
variable is of type int
,
since the condition of the if
block checks that width is int
.
If width
is a mutable identifier, it would be unsafe if the compiler smart casts it without a
warning.
That is why you have to declare a mut
before the is
expression:
Otherwise width
would keep its original type.
This works for both, simple variables and complex expressions like user.name
: