Learning Cairo - Enumerations (11)

Learning Cairo - Enumerations (11)

Prerequisite

Install cairo-run.

Enumerations

In this article, we will learn about enumerations, or enums, which are a way to define custom data types. Enums can be very useful in certain scenarios because they are both simple and convenient to use.

Let's take a look at an example of an enum:

#[derive(Drop)]
enum Direction {
    North: (),
    East: (),
    South: (),
    West: (),
}

In this example, we've defined an enum called Direction, which includes four members: North, East, South, and West. Each member is associated with a uint type (). You can instantiate it using this syntax:

let direction = Direction::North(());

The types associated with enum members can also be customized, for example:

#[derive(Drop)]
enum Message {
    Quit: (),
    Echo: felt252,
    Move: (u128, u128),
}

Here, the Message enum has three members: Quit, Echo, and Move, each with different types:

  • Quit is of type unit - it has no associated data.
  • Echo is of type felt252.
  • Move is a tuple consisting of two u128 values.

Enum members can also use result types or other enums.

We can also define traits for custom enums, for example:

trait Processing {
    fn process(self: Message);
}

impl ProcessingImpl of Processing {
    fn process(self: Message) {
        match self {
            Message::Quit(()) => {
                'quitting'.print();
            },
            Message::Echo(value) => {
                value.print();
            },
            Message::Move((x, y)) => {
                'moving'.print();
            },
        }
    }
}

In the above example, we've implemented the Processing trait for the Message enum. If you run the following code:

let msg: Message = Message::Quit(());
msg.process();

It will print quitting.

Cairo includes an Option enum, representing the concept of an optional value. It has two variants: Some: T and None: (). Some: T indicates the presence of a value of type T, while None indicates the absence of a value.

enum Option<T> {
    Some: T,
    None: (),
}

The Option enum is useful for explicitly representing the possibility of a value not existing, making our code more expressive and easier to reason about. Using Option can also help prevent errors caused by using uninitialized or unexpected null values.

In the following example, there is a function that returns the index of the first occurrence of a given value in an array, or None if the value does not exist. We demonstrate two methods:

  • find_value_recursive (recursive)
  • find_value_iterative (iterative)
use array::ArrayTrait;
use debug::PrintTrait;
use option::OptionTrait;

fn find_value_recursive(arr: @Array<felt252>, value: felt252, index: usize) -> Option<usize> {
    if index >= arr.len() {
        return Option::None(());
    }

    if *arr.at(index) == value {
        return Option::Some(index);
    }

    find_value_recursive(arr, value, index + 1)
}

fn find_value_iterative(arr: @Array<felt252>, value: felt252) -> Option<usize> {
    let length = arr.len();
    let mut index = 0;
    let mut found: Option<usize> = Option::None(());
    loop {
        if index < length {
            if *arr.at(index) == value {
                found = Option::Some(index);
                break;
            }
        } else {
            break;
        }
        index += 1;
    };
    return found;
}

#[test]
#[available_gas(999999)]
fn test_increase_amount() {
    let mut my_array = ArrayTrait::new();
    my_array.append(3);
    my_array.append(7);
    my_array.append(2);
    my_array.append(5);

    let value_to_find = 7;
    let result = find_value_recursive(@my_array, value_to_find, 0);
    let result_i = find_value_iterative(@my_array, value_to_find);

    match result {
        Option::Some(index) => {
            if index == 1 {
                'it worked'.print();
            }
        },
        Option::None(()) => {
            'not found'.print();
        },
    }
    match result_i {
        Option::Some(index) => {
            if index == 1 {
                'it worked'.print();
            }
        },
        Option::None(()) => {
            'not found'.print();
        },
    }
}

Running this code will print it worked.

Conclusion

Enums are a valuable data type in software development, simplifying many scenarios and making code more readable and manageable. They are a powerful tool to have in your programming toolkit.

Low latency and free Starknet node awaits!

For a limited time, Reddio is offering unrestricted access to its high-speed StarkNet Node, completely free of charge. This is an unparalleled opportunity to experience the fastest connection with the lowest delay. All you need to do is register an account on Reddio at https://dashboard.reddio.com/ and start exploring the limitless possibilities.

You can discover why Reddio claims the fastest connection by reading more here.