Skip to content

Instantly share code, notes, and snippets.

@RUSShyTwo
Last active December 2, 2021 20:05
Show Gist options
  • Save RUSShyTwo/2fcf6d294d25ba748d61927b5eed2944 to your computer and use it in GitHub Desktop.
Save RUSShyTwo/2fcf6d294d25ba748d61927b5eed2944 to your computer and use it in GitHub Desktop.

Enum Literals

Field Value
DIP: (number/id -- assigned by DIP Manager)
Review Count: 0 (edited by DIP Manager)
Author: RUSShy
Implementation: (links to implementation PR if any)
Status: Will be set by the DIP manager (e.g. "Approved" or "Rejected")

Abstract

Enums are very usefull, but often tends to bloat the code because we have to prefix enum values with the type name

Other languages shows we could be smarter about it and let just ommit the type all together

This makes using enums more conveniant to use, with less typing

They are just enums after all..

enum MyTag
{
    A, B, C
}
MyTag tag = .A;
void what(MyTag tag)
{}
what(.B);

boom

Contents

Rationale

When using a lot of enums, typing their name become a chore, let save some typing for later more important code

We could use with to workaround this issue, but this pollutes the scope, that's not what we want, we want to be implicit when we use enums, not being too open, it would cause other issues like symbol/name clash

Prior Work

Description

Examples:

enum MySuperLongAction
{
    DO_ACTION_REST,
    DO_ACTION_X,
    DO_ACTION_Y,
    DO_ACTION_ABC,
    DO_ACTION_77777,
}

struct MyAction
{
    MySuperLongAction action;

    void change_to(MySuperLongAction action)
    {
        this.action = action;
        if (action == MySuperLongAction.DO_ACTION_77777)
        {
            // do something
        }

        if (action != MySuperLongAction.DO_ACTION_ABC)
        {
            // do something
        }
    }


    void tick()
    {
        if (action == MySuperLongAction.DO_ACTION_REST) return;

        // compute some stuff
        
        switch (action) with (MySuperLongAction)
        {
            case DO_ACTION_X; // do stuff break;
            case DO_ACTION_Y; // do stuff break;

            default: break;
        }
    }
}


MyAction action;
action.change_to(MySuperLongAction.DO_ACTION_Y);
action.tick();

becomes:

enum MySuperLongAction
{
    DO_ACTION_REST,
    DO_ACTION_X,
    DO_ACTION_Y,
    DO_ACTION_ABC,
    DO_ACTION_77777,
}

struct MyAction
{
    MySuperLongAction action;

    void change_to(MySuperLongAction action)
    {
        this.action = action;
        if (action == .DO_ACTION_77777)
        {
            // do something
        }

        if (action != .DO_ACTION_ABC)
        {
            // do something
        }
    }


    void tick()
    {
        if (action == .DO_ACTION_REST) return;

        // compute some stuff
        
        switch (action)
        {
            case DO_ACTION_X; // do stuff break;
            case DO_ACTION_Y; // do stuff break;

            default: break;
        }
    }
}


MyAction action;
action.change_to(.DO_ACTION_Y);
action.tick();

We remove a lot of unnecessary repetition, the code is cleaner and more elegant

Unlike with C, we still get type safety!

Breaking Changes and Deprecations

I don't think that's a breaking change

The only problem i could see would be where we use . to call imported symbols

If such case happen, the compiler should just emit an error or we could use a different syntax

  • #
  • :
  • @

The other problem i could see is with overloaded functions, or with enums with similar names

But there again, the compiler should just emit an error if it sees any ambiguous calls

Reference

https://ziglang.org/documentation/master/#Enum-Literals

https://odin-lang.org/docs/overview/#implicit-selector-expression

Copyright & License

Public Domain

Reviews

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment