Why is @enum 0-based?

Arrays in Julia are 1-based, so why are Enums 0-based?

julia> Base.Enums.@enum ABC begin

julia> ABC(0)
A::ABC = 0

This was just recently discussed on Slack, in the gripes channel:


They’re partly designed for C interop which is probably why they’re like that - Stefan K.

I think they should start at 1 in a language like Julia (ie. using them as indexes), you could open an issue if you agree, or a PR, if you can change it yourself.

They will tell you that you can do:

@enum RoundFoods Cookie=1 Cake Pizza Pie

but that should be the default IMHO, and people using it for C interop, should be the one doing:

@enum RoundFoods Cookie=0 Cake Pizza Pie

Instead, as this is a generic language feature, not an interop specific feature.

It’s still breakage season, so why not? Better to have consistency across the language, good luck convincing them though.


I thought so.

I think it’s not too bad, because when you want to use them you usually don’t care about the actual values, and when you actually care about the values you probably want to specify them yourself.


I was about to ask the same question on here, and then I found this thread. I agree that enums should be one based. Sure, most of the time it doesn’t matter, and you can explicitly set the levels if you really want to, but just now I needed to create an array with my enums, like this,

julia> @enum Fruit apple orange kiwi

julia> Fruit.(0:2)
3-element Array{Fruit,1}:
 apple::Fruit = 0 
 orange::Fruit = 1
 kiwi::Fruit = 2

and it just hurt a little inside that I had to start my “indexing” at zero. It feels totally against the spirit of Julia’s (default) 1-based indexing.

Because enums aren’t arrays? They are a wrapper for a kind of integer type, and integer types on a computer have values that generally start at 0, especially for unsigned types.

You might as well ask why UInt8 values go from 0 to 255 and not 1 to 256, or why Bool values are equivalent to 0 and 1 rather than 1 and 2.

Indeed, you can define an @enum to be a wrapper around an unsigned integer or a boolean value, in which case starting the numbering at 1 by default would allow fewer possible values. For example, @enum Switch::Bool begin Off; On; end couldn’t work.


Wow, it makes a lot more sense when you put it that way! The @enum Switch::Bool begin On; Off; end example really drives the point home. As an aside, I’ve read the docs for @enum, but I hadn’t quite realized that @enum EnumName[::BaseType] meant I could optionally annotate my enum type name, even though I know that’s how square brackets are used in other parts of the docs. So thanks on both accounts!

1 Like

I have to agree, this really makes sense now.