An enum is a type with a fixed set of named variants. Simple enums are just labels (colours, directions). Variants can also carry data, so you can say "a shape is either a circle with a radius or a rectangle with width and height." Pattern matching lets you inspect which variant you have and pull out its fields.
enum Color {
RED
GREEN
BLUE
}
let c = Color.RED
print(c) # RED
Simple enums compile to JVM enum classes.
Enum variants can carry data:
enum Shape {
Circle(radius: Float)
Rectangle(width: Float, height: Float)
Point
}
def describe(s: Shape) -> Str {
match s {
case Shape.Circle(r) {
return f"circle with radius {r}"
}
case Shape.Rectangle(w, h) {
return f"{w}x{h} rectangle"
}
case Shape.Point {
return "point"
}
}
}
let c = Shape.Circle(5.0)
print(describe(c)) # circle with radius 5.0
Payload variants are constructed like function calls and destructured in match/case arms. Simple and payload variants can be mixed in the same enum. Payload enums compile to a sealed class hierarchy on the JVM.
let x = 2
match x {
case 1 {
print("one")
}
case 2 | 3 {
print("two or three")
}
case n if n > 10 {
print(f"big: {n}")
}
case _ {
print("other")
}
}
Match works with literal values, enums, tuples, and a wildcard _ for the default case. Guards use if after the pattern. Or-patterns use | to match multiple values.
match point {
case (0, 0) {
print("origin")
}
case (x, 0) {
print(f"on x-axis at {x}")
}
case (0, y) {
print(f"on y-axis at {y}")
}
case (x, y) {
print(f"({x}, {y})")
}
}
match result {
case Ok(value) {
print(f"got {value}")
}
case Err(error) {
print(f"failed: {error}")
}
}
The compiler checks exhaustiveness for enum matches and warns if you don't cover all variants.