45
votes

Rust's enums are algebraic datatypes. As far as I can tell this seems to subsume what struct is. What is different about struct that necessitates keeping it?

4
This has been asked on Stack Overflow several times, though I don’t have time just now to find links. Probably not hard to find.Chris Morgan
@ChrisMorgan, if such a thing exists (I don't think it does), it is very hard to find. Of all the questions for "struct enum", this is the closest, but it's not the same question at all.huon

4 Answers

42
votes

First of all, you are correct that semantically enum is strictly superior to the struct as to what it can represent, and therefore struct is somewhat redundant.

However, there are other elements at play here.

  • ease of use: the values within an enum can only be accessed (directly) through matching; contrast with the ease of use of accessing a struct field. You could write accessors for each and every field, but that is really cumbersome.

  • distinction: an enum is a tagged union, a struct has a fixed-layout; we (programmers) generally like to put labels on things, and therefore giving different names to different functionality can be appreciated.

As I see it, struct is therefore syntactic sugar. I usually prefer lean and mean, but a bit of sugar can go a long way in increasing what can be represented tersely.

24
votes

Firstly, Rust has a wide array of data types:

  • Structs with named fields (struct Foo {bar: uint})
  • Tuple structs (struct Foo(pub Bar, Baz))
  • Structs with no fields (struct Foo;)
  • Enums, with various types of variants:
    • Variants with no fields (eg None)
    • Tuple variants (eg Some(T))
    • Struct variants (eg Some { pub inner :T })

This gives the programmer some flexibility in defining datatypes. Often, you don't want named fields, especially if the struct/variant has only one field. Rust lets you use tuple structs/tuple variants in that case.

If structs were removed from Rust there would be no loss of functionality, enums with struct variants could be used again. But there would be an overwhelming number of single-variant enums which would be unnecessary and cumbersome to use.

12
votes

Not 100% correct, but another nice way to think about it : enum isn't actually superior to struct, the syntax sugar just makes it look like it is.

An enum is a sum type meaning that it's value is one value of one of a set of other types. The Result<T, E> type is either of type T or E. So each enum variant has exactly one type associated with it. Everything else (no type, tuple variants and struct variants) could be syntax sugar.

enum Animal {
    // without syntax sugar
    Cat(i32),  
    // desugars to `Dog(())` (empty tuple/unit) 
    Dog,
    // desugars to `Horse((i32, bool))` (tuple)
    Horse(i32, bool),
    // desugars to `Eagle(GeneratedEagleType)` and a struct definition outside
    // of this enum `struct GeneratedEagleType { weight: i32, male: bool }`
    Eagle { weight: i32, male: bool }
}

So it would be enough if each enum variant would be associated with exactly one type. And in that case enum is not superior to struct, because it cannot construct product types (like struct).

To be able write the "type definition" inside the enum variant definition is just for convenience.

Also: struct is superior to "tuple structs" and "tuples", too. If we ignore the names those three things are nearly equivalent. But Rust still has those three different kinds of types for convenience.


Please note that I don't know if those enum definitions are actually syntax sugar or not. But they could be and that might help think about. it

2
votes

Visibility

Not to find reason in what may be a transient implementation detail (I'm not on the core team and have no insight), but

  • A public enum can not hold or contain a private struct.
  • A public struct can hold or contain a private enum.

See also