Enum
enum declares a closed set of variants. Variants can carry no data or carry a payload; together with match, structured branching over mutually exclusive cases becomes a first-class construct.
Declaration Forms
enum Color
{
Red,
Green,
Blue,
}
enum Light
{
Off,
Blink(times: int),
On(brightness: float),
}Color is a pure marker enum; Light’s variants carry positional payloads (a named times: int or a bare type both work, but the style must be consistent within one enum). The generic enum enum Opt<T> { Some(T), None } is equally legal.
Construction and Reflection
val c = Color.Green;
print(c, c.name, c.ToString());
print(Color.Blue);
val variants = Color.Variants();
print(variants.Count);
val parsed = try? Color("Blue");
print(parsed ?? Color.Red);
val bad = try? Color("Purple");
print(bad == null);Green Green Green
Blue
3
Blue
True- Static names are the constructors:
Color.Greenyields the value directly. Variants()returns a list of all variants.Color("Green")parses by string name and must be consumed through the error flow; failure goes down failSystem.ConversionError. Enums with payload variants do not support string parsing.
Payload Variants
val l = Light.Blink(3);
print(l.ToString());
val brightness = match l
{
Light.Off => 0.0,
Light.Blink(t) => t as float,
Light.On(b) => b,
};
print(brightness);Blink(3)
3For payload variants, ToString() prints in the form VariantName(payload…). For destructuring payloads in match, see the exhaustiveness checks on the Match page: missing any variant fails to compile.
Generic Enums
Type parameters make the payload generic; the most typical case is the optional value:
enum Opt<T>
{
Some(value: T),
None,
}
val o = Opt.Some(5);
val n = Opt<string>.None;
print(n == Opt<string>.None);
val sum = match o
{
Opt.Some(v) => v,
Opt.None => 0,
};
print(sum);True
5Type arguments are usually inferred from the constructor arguments (Opt.Some(5) gives Opt<int>). match arms use the non-generic qualified name Opt.Some(v); patterns never spell out type arguments.
Printing and ToString() show the bare variant name plus payload (Opt.Some(5) prints Some(5)), without type arguments.
is is True for enum types. For generic instantiations, is judges by declaration identity and does not expand type arguments: both Opt.Some(5) is Opt<int> and is Opt<string> are True, so don’t use is to discriminate type arguments.
Enum type parameters can also carry where constraints, with the same constraint surface as generic types:
import Math.*;
enum Measure<T> where T: Numeric
{
Value(v: T),
Zero,
}
val m = Measure.Value(5);
print(m);Value(5)