Language
Enums
def enum declares a type whose values are one of a fixed list of variants.
Plain enums
def enum Color { Red, Green, Blue }
var c = Color.Green
print(c, c == Color.Green, c as int, Color.Red < Color.Blue)prints Green true 1 true.
- A variant is written with the enum's name,
Color.Green. Inside amatchon aColor, the bare nameGreenworks too. - Each variant has a number, counting from
0in the order they are declared.c as intgives it, and variants compare with<and>in that order. n as Colorturns a number back into a variant. It is not checked, so only use numbers that came fromas int.- A plain enum is a number at runtime: it costs nothing to copy or compare, and works as a map key
(
{Color.Red: "stop"}). - It prints as the variant's name, and
"${c}"andc as stringgive that name. - The zero value of a plain enum (for a variable or field declared without a value) is its first variant.
Variants with data
A variant can carry fields, written in parentheses like the parameters of a function:
def enum Shape {
Circle(radius: float),
Rect(w: float, h: float),
Dot
}
fun area(s: Shape): float {
return match s {
Shape.Circle(r) => 3.14159 * r * r
Shape.Rect(w, h) => w * h
Shape.Dot => 0.0
}
}
var shapes = [Shape.Rect(2.0, 3.0), Shape.Circle(1.0), Shape.Dot]
for s in shapes {
print(s, area(s))
}- A variant with fields is built like a function call:
Shape.Rect(2.0, 3.0). A variant without fields is used as it is:Shape.Dot. - Values print the way they are built:
Shape.Rect(2.0, 3.0),Shape.Dot. ==compares the variant and then the fields:Shape.Circle(1.0) == Shape.Circle(1.0)istrue.- The fields cannot be changed after the value is built. Build a new value instead.
- Variants with data cannot be converted to numbers with
as int.
Reading the fields
match takes a value apart; see variant patterns. To read one variant's
fields without a match, check the variant with is, which narrows the value:
def enum Shape {
Circle(radius: float),
Dot
}
fun radiusOf(s: Shape): float {
if (s is Shape.Circle) {
return s.radius
}
return 0.0
}
print(radiusOf(Shape.Circle(2.5)), radiusOf(Shape.Dot))Shape.Circle is a type here, so s is Shape.Circle, s as? Shape.Circle and is Shape.Circle c in a match all
work.
Recursive enums
An enum with data is a reference type, like a struct, so a variant can hold values of its own enum:
def enum Tree {
Leaf(value: int),
Node(left: Tree, right: Tree)
}
fun sum(t: Tree): int {
return match t {
Tree.Leaf(v) => v
Tree.Node(l, r) => sum(l) + sum(r)
}
}
print(sum(Tree.Node(Tree.Leaf(1), Tree.Node(Tree.Leaf(2), Tree.Leaf(3)))))Adding functions to an enum
An enum body only lists variants. Functions that work on the enum are written outside it, and work as methods through method syntax:
def enum Light { Red, Yellow, Green }
fun next(l: Light): Light {
return match l {
Red => Light.Green
Green => Light.Yellow
Yellow => Light.Red
}
}
print(Light.Red.next(), Light.Red.next().next())Limits
- Variants cannot be given their own numbers (
Red = 2is an error); they are numbered in order. - Enums cannot take type parameters. Use a nullable type instead of an
Option, and a genericdef typeor a struct for the rest. - An enum cannot implement an interface; write the functions outside it as shown above.