Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Enums

What is an enum? An enum essentially is just a number under the hood, but one with very interesting properties. It can be thought of as a tag which can only have one of a selected number of tags. Here is an example:

use Core.print

enum MyEnum:
    TAG1, TAG2, TAG3;

def main():
    MyEnum my_enum = MyEnum.TAG1;

    if my_enum == MyEnum.TAG1:
        print("is TAG1\n");
    else if my_enum == MyEnum.TAG2:
        print("is TAG2\n");
    else if my_enum == MyEnum.TAG3:
        print("is TAG3\n");
    else:
        print("This code path is actually impossible to reach, no matter which value 'my_enum' has!\n");

This program will print this line to the console:

is TAG1

As you can see, defining our own enum is very simple. We write the enum keyword followed by the name of the enum, similar how we define the name of data. As you can see, the name MyEnum is now a new user-defined type, which is the reason why a variable (my_enum) can be declared to be of type MyEnum. Then, we write a colon : to signify the "body" of the enum, where we define all the values the enum could have. And then, we define the tag names the enum could have. Each tag name has to be unique within the same enum, so we would not be allowed to define TAG1 twice. Tags are comma-separated and Flint sees everything as a tag until it finds a semicolon ;.

If you dont like the horizontal layout, you can also define an enum like so:

enum MyEnum:
    TAG1, // Some description of TAG1
    TAG2, // Some description of TAG2
    TAG3; // Some description of TAG3

Comparing Enums

Enums are considered equal if their type and their tag match. Here is an example of what this means:

use Core.print

enum Enum1:
    TAG1, TAG2, TAG3;

enum Enum2:
    TAG1, TAG2, TAG3;

def main():
    Enum1 e1 = Enum1.TAG1;

    if e1 == Enum2.TAG1:
        print("is Enum2.TAG1!\n");

This program will print this error to the console:

Parse Error at main.ft:12:8
 -- Type mismatch of expression e1 == Enum2.TAG1
 -- Expected Enum1 but got Enum2

The error message differs in the current version of the compiler.

The above error message is the message that should be displayed. But in its current form the compiler will produce this error message instead:

Parse Error at main.ft:1:1
 -- Type mismatch of expression EOF
 -- Expected Enum1 but got Enum2

There is no information contained where the mismatch happened or what the expression the error happened in was. This will be fixed eventually, but requires some changes in unrelated areas of the compiler, so it might take a while for it to be fixed.

Enums with functions

Enums are considered to be non-complex data types in Flint, even though they are user-defined. So, we can easily pass in enums to a function and return them from it:

use Core.print

enum ComparisonResult:
    BIGGER, SMALLER, EQUAL;

def compare(i32 x, i32 y) -> ComparisonResult:
    if x > y:
        return ComparisonResult.BIGGER;
    else if y < x:
        return ComparisonResult.SMALLER;
    else:
        return ComparisonResult.EQUAL;

def main():
    ComparisonResult result = compare(10, 5);
    if result == ComparisonResult.BIGGER:
        print("is bigger\n");
    else if result == ComparisonResult.SMALLER:
        print("is smaller\n");
    else if result == ComparisonResult.EQUAL:
        print("is equal\n");
    else:
        print("Impossible to reach code block\n");

This program will print this line to the console:

is bigger

The above program is very useless, though, as it would be much more efficient to remove the enum entirely and just use the comparisons directly. But these examples are not always meant to be absolutely useful, they are there to get a point across. So, we can not only return enums from a function but also pass them to a function. Lets dive into a bit bigger example now.

use Core.print

enum Operation:
    PLUS, MINUS, MULT, DIV;

data NumberContainer:
    i32 a;
    f32 b;
    u64 c;
    NumberContainer(a, b, c);

def apply_operation(mut NumberContainer container, Operation op, f32 value):
    if op == Operation.PLUS:
        container.(a, b, c) += (i32(value), value, u64(value));
    else if op == Operation.MINUS:
        container.(a, b, c) -= (i32(value), value, u64(value));
    else if op == Operation.MULT:
        container.(a, b, c) *= (i32(value), value, u64(value));
    else if op == Operation.DIV:
        container.(a, b, c) /= (i32(value), value, u64(value));

def main():
    NumberContainer container = NumberContainer(-10, 22.5, u64(889));
    print($"container.(a, b, c) = ({container.a}, {container.b}, {container.c})\n");

    apply_operation(container, Operation.PLUS, 3.4);
    print($"container.(a, b, c) = ({container.a}, {container.b}, {container.c})\n");

    apply_operation(container, Operation.MULT, 7.2);
    print($"container.(a, b, c) = ({container.a}, {container.b}, {container.c})\n");

    apply_operation(container, Operation.MINUS, 22.1);
    print($"container.(a, b, c) = ({container.a}, {container.b}, {container.c})\n");

    apply_operation(container, Operation.DIV, 6.9);
    print($"container.(a, b, c) = ({container.a}, {container.b}, {container.c})\n");

This program will print these lines to the console:

container.(a, b, c) = (-10, 22.5, 889)
container.(a, b, c) = (-7, 25.9, 892)
container.(a, b, c) = (-49, 186.479996, 6244)
container.(a, b, c) = (-71, 164.37999, 6222)
container.(a, b, c) = (-11, 23.823187, 1037)