3
$\begingroup$

I don't know the standard words for these, but:

  • complex enum is like enum { E1(t1: T1, t2: T2, ...), E2(...), ... }
  • simple enum is like enum { E1(T1), E2(T2), ... }

The difference is for the constructor, the simple one always contain a tag and a type, the complex one contains a tag and multiple name-type pairs.

In a language with struct, you can always simulate complex enum by simple enum + struct, and the simple version feels much orthogonal.

But most languages even toy ones prefer complex enum. Why?


Example:

A complex enum:

enum Ast { TypeDef(name: Str, body: Ast), Ident(str: Str) }

simple enum:

enum Ast { TypeDef(TypeDef), Ident(Str) }
struct TypeDef { name: Str, body: Ast }
$\endgroup$
8
  • $\begingroup$ @Isaiah I am confused. The question sounds crystal clear to me. What in particular do you think is confusing? The OP has given examples already. $\endgroup$
    – ice1000
    May 19, 2023 at 3:22
  • 11
    $\begingroup$ Is this really true? What you call a "complex enum" is normally called an algebraic data type, though it is called an "enum" in e.g. Rust. On the other hand, enums in most languages I know are simply enumerated lists of values, often represented by consecutive integers, with no further structure. The kind you call a "simple enum" looks like what I would call a "sum type" or "tagged union", and I don't know of any languages that call this an enum. $\endgroup$
    – kaya3
    May 19, 2023 at 4:02
  • 2
    $\begingroup$ @kaya3 I fear whatever terminology I use they might defined differently by other people. So I just came up with my own definition. For example what you calls sum type only have two constructors, but what I call "simple enum" can have multiple ones. $\endgroup$
    – molikto
    May 19, 2023 at 4:07
  • 3
    $\begingroup$ I don't think "sum type" has the connotation of only two constituents, but "tagged union" certainly doesn't. I think your phrase "simple enum" is misleading because people would expect this to mean traditional enums, i.e. enumerated lists of values with no further structure. In any case it is better to use established terminology rather than invent your own. $\endgroup$
    – kaya3
    May 19, 2023 at 4:13
  • 2
    $\begingroup$ So, if "most languages" is correct, @molikto, please add at least one example. $\endgroup$
    – feldentm
    Jan 29 at 16:20

2 Answers 2

5
$\begingroup$

I feel mainly two reasons:

  1. Structs corresponding to a single enum variant needs a name, while they have only one canonical use case, so it might be desirable to make these structs anonymous, hence the inlined version.
  2. If your language supports tuples, it's definitely going to be a common pattern for users to have E1((T1, T2, ...)), which, the ability to unwrap the parentheses would be syntactically convenient. This is no longer a case when the syntax of enum variant types are not using parentheses already, see comments.
  3. You can implement the simple enums in the core language and implement an elaboration feature. This is good for both compiler and the users.
  4. Enums were evolved from C enums where no fields are allowed, which is a special case of n-ary (complex) enums, but slightly more cumbersome with simple ones.
$\endgroup$
3
  • $\begingroup$ for 1, say I have enum Ast { TypeDef(name: ..., body:...) }. I always found I will need to define a function on TypeDef. So I ends up writting enum Ast { TypeDef(TypeDef) } where TypeDef isn't inlined. $\endgroup$
    – molikto
    May 19, 2023 at 3:25
  • $\begingroup$ for 2, is it a syntax thing? What if the syntax for tagging is t1@T1? Then the syntax will be less noisy $\endgroup$
    – molikto
    May 19, 2023 at 3:26
  • $\begingroup$ I've edited my answer to address your questions. $\endgroup$
    – ice1000
    May 19, 2023 at 3:31
3
$\begingroup$

One advantage of "complex enums" over "simple enums" combined with separately defined structs is that not having the structure be a type in it's own right can enable more efficient packing of the members.

A common constraint in programming languages is that the size of a type must be a multiple of it's alignment requirement. If you don't have that constraint then the definition of arrays gets rather messier.

If you have a "complex enum" as a single data type, and either you allow the compiler to reorder fields or you have the programmer order fields in the most efficient manner then you only pay the price for rounding up to the next multiple of the alignment requirement once. On the other hand if you nest a struct inside a "simple enum" you pay that penalty twice.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .