Enums are a data type composed of a fixed set of inner data types, known as variants. A common use is to define an "optional" or "maybe" type that will either have a "something" of X, or a nothing.

In addition to providing an Option as part of predefined data types, it is also possible to create new enums.

Declaration

By default, an enum is flat. The variants of a flat enum are placed into the module's namespace.

enum FlatRgb
{
    Red,
    Green,
    Blue

    define is_blue: Boolean
    {
        match self: {
            case Blue: return true
            else:      return false
        }
    }
}

var v = Blue

print(v.is_blue()) # true
print(v) # Blue

The alternative is a scoped enum. Variants of a scoped enum are kept within the enum.

scoped enum ScopedRgb
{
    Red,
    Green,
    Blue

    define is_blue: Boolean
    {
        match self: {
            case ScopedRgb.Blue:
                return true
            case ScopedRgb.Red,
                 ScopedRgb.Green:
                return false
        }
    }
}

var v = ScopedRgb.Blue

print(v.is_blue()) # true
print(v) # ScopedRgb.Blue

In both cases, variants are sealed inside of the enum they are declared in. It is not possible to, for example, declare a variable of type Some.

Methods

Similar to classes, enum allow declaration of methods. Enum methods do not support any qualifiers. All enum methods act as they are public, and receive self as a hidden first parameter. Enum methods do not allow a scope because they cannot inherit or be inherited from.

enum Rgb
{
    Red,
    Green,
    Blue

    define is_blue: Boolean
    {
        with self as Blue: {
            return true
        else:
            return false
        }
    }
}

var v = Blue

print(v.is_blue())    # true

# An alternative way of calling the above.
print(Rgb.is_blue(v)) # true
print(v)              # Blue

Arguments

It is possible for a variant to take arguments. Those arguments can include the enum itself. Variants that take values can be called like a Function, but they are not Function values.

Variants support all argument types, except optional arguments.

enum Tree
{
    Leaf(Integer),
    Branch(Tree, Tree)

    define walk: Integer
    {
        match self: {
            case Leaf(value):
                return value
            case Branch(left, right):
                return left.walk() + right.walk()
        }
    }
}

var tree =
    Branch(
        Branch(
            Leaf(10),
            Leaf(20)
        ),
        Leaf(30)
    )

print(tree.walk()) # 60

Variants can also have variable arguments.

enum Tree
{
    Leaf(Integer),
    Branch(Tree...)

    define walk: Integer
    {
        match self: {
            case Leaf(value):
                return value
            case Branch(targets):
                var total = 0

                for i in 0...targets.size() - 1: {
                    total += targets[i].walk()
                }

                return total
        }
    }
}

var tree =
    Branch(
        Branch(
            Leaf(10)
        ),
        Leaf(20),
        Leaf(30),
        Leaf(40)
    )

print(tree.walk()) # 100

Keyword arguments are also supported.

enum Color
{
    Blue,
    Green,
    Red,
    RGB(:red Integer, :green Integer, :blue Integer)

    define to_i: Integer
    {
        match self: {
            case Blue:
                return 0x0000ff
            case Green:
                return 0x00ff00
            case Red:
                return 0xff0000
            case RGB(r, g, b):
                return (r << 16) +
                       (g << 8) +
                       b
        }
    }
}

var v = RGB(:red 0xff,
            :blue 0,
            :green 0)

print(Green.to_i()) # 65280
print(v.to_i())     # 16711680

Variants support call piping.

{
    var v = Option.unwrap(Some(1))

    print(v) # 1
}
{
    var v = 1 |> Some |> Option.unwrap

    print(v) # 1
}