The value of enums


(Tino) #1

Enums are a fundamental part of Swift, so I guess they won't change much — but I wonder if anyone shares my observations in real-life use…

Afair, there are three different types of enums:
- Enums with raw values
- enums with associated objects
- Plain enums (no underlying value)

I use the first type quite often (as a convenient way to create string constants, or for serialization), but see no real value in plain enums (they offer nothing over enums backed with a raw value).

The second type is special:
It looks like a really cool concept, and and I started several designs based on them — just to realize later that structs and classes are a better fit.
My conclusion so far is that enums perform bad as soon as you want to attach additional data or behavior; one or two computed properties are ok, but those switch-statements quickly become a burden.
There are some options to work around this problem, but I guess I'll just stay away from enums with associated objects by default (with the exception of error-types — imho those can be modeled quite nicely).

So, that's my current perception, and I'm curious if others had similar experiences — or, even more interesting, completely different observations and elegant solutions based on enums.

- Tino


(Erica Sadun) #2

Enums:

* Great for umbrella type implementation
* Plain enums: perfect for enumeratable states and defining roles.
* Associated types: I use them mostly for Result type, but also handy for things like
  JSON parsers, which are Swift's mandated follow-on to "Hello World"
* Enums with raw values: I mostly stick to stringity ones, where there's a state or role but
  I want to have easy access to the name as well as the role, and integer ones, where I can
  repurpose the number elsewhere
* I really love using enums with switch statements, and compiler guarantees of case
   completeness.

I'd put forth that enum cases should be few, simple, and focused. They should not be
used as flags. When used well, they should feel obvious and integrate well into
switch statements.

-- E

···

On Nov 6, 2016, at 4:07 AM, Tino Heth via swift-users <swift-users@swift.org> wrote:

Enums are a fundamental part of Swift, so I guess they won't change much — but I wonder if anyone shares my observations in real-life use…

Afair, there are three different types of enums:
- Enums with raw values
- enums with associated objects
- Plain enums (no underlying value)

I use the first type quite often (as a convenient way to create string constants, or for serialization), but see no real value in plain enums (they offer nothing over enums backed with a raw value).

The second type is special:
It looks like a really cool concept, and and I started several designs based on them — just to realize later that structs and classes are a better fit.
My conclusion so far is that enums perform bad as soon as you want to attach additional data or behavior; one or two computed properties are ok, but those switch-statements quickly become a burden.
There are some options to work around this problem, but I guess I'll just stay away from enums with associated objects by default (with the exception of error-types — imho those can be modeled quite nicely).

So, that's my current perception, and I'm curious if others had similar experiences — or, even more interesting, completely different observations and elegant solutions based on enums.


(Dave Abrahams) #3

I have personally always found that exuberant use of that kind of enum
results in ergonomics and readability difficulties. There are several
things we have thought of that could potentially improve the situation,
most notably exposing each case as an optional property. I'd also
really like to see switch-expressions (as opposed to statements). I'm
not sure if that's really all we need in order to allow enums to reach
their potential, though.

···

on Sun Nov 06 2016, Tino Heth <swift-users-AT-swift.org> wrote:

Enums are a fundamental part of Swift, so I guess they won't change
much — but I wonder if anyone shares my observations in real-life use…

Afair, there are three different types of enums:
- Enums with raw values
- enums with associated objects
- Plain enums (no underlying value)

I use the first type quite often (as a convenient way to create string
constants, or for serialization), but see no real value in plain enums
(they offer nothing over enums backed with a raw value).

The second type is special:
It looks like a really cool concept, and and I started several designs
based on them — just to realize later that structs and classes are a
better fit.
My conclusion so far is that enums perform bad as soon as you want to
attach additional data or behavior; one or two computed properties are
ok, but those switch-statements quickly become a burden.
There are some options to work around this problem, but I guess I'll
just stay away from enums with associated objects by default (with the
exception of error-types — imho those can be modeled quite nicely).

So, that's my current perception, and I'm curious if others had
similar experiences — or, even more interesting, completely different
observations and elegant solutions based on enums.

--
-Dave


(Rien) #4

As usual: it depends.

I use enums with associated values quite a lot.
In my experience there is quite a thin line between very convenient and too much.
I have several cases where I started off with enums with associated values, only to later convert them to classes.
As long as the enums only have an associated value, things tend to work just fine. But as soon as more properties become associated with the enum, things get out of hand.
Once I tried to fix a complete inter process protocol in enum’s. And it did work, but maintenance became a nightmare after the protocol implemented more than 10 commands or so.
To me the key is: keep them small.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl

···

On 06 Nov 2016, at 12:07, Tino Heth via swift-users <swift-users@swift.org> wrote:

Enums are a fundamental part of Swift, so I guess they won't change much — but I wonder if anyone shares my observations in real-life use…

Afair, there are three different types of enums:
- Enums with raw values
- enums with associated objects
- Plain enums (no underlying value)

I use the first type quite often (as a convenient way to create string constants, or for serialization), but see no real value in plain enums (they offer nothing over enums backed with a raw value).

The second type is special:
It looks like a really cool concept, and and I started several designs based on them — just to realize later that structs and classes are a better fit.
My conclusion so far is that enums perform bad as soon as you want to attach additional data or behavior; one or two computed properties are ok, but those switch-statements quickly become a burden.
There are some options to work around this problem, but I guess I'll just stay away from enums with associated objects by default (with the exception of error-types — imho those can be modeled quite nicely).

So, that's my current perception, and I'm curious if others had similar experiences — or, even more interesting, completely different observations and elegant solutions based on enums.

- Tino
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


#5

To the topic at hand, the project I’m currently working on has 2 enums,
both with String raw values. For comparison, it has 3 classes (a Formatter
subclass, the app delegate, and one more), 4 protocols, and 47 structs.

One of the enums exists to select among the handful of struct types which
conform to one of the protocols.

There are several things we have thought of that could potentially improve
the situation, most notably exposing each case as an optional property.

That would be very nice.

I'd also really like to see switch-expressions (as opposed to statements).

Hmm, would a syntax like this be appropriate?

switch someValue -> [String] {
    case .helloWorld: return ["Hello", "world"]
    default: return []
}

That way the existing switch statement could remain as-is, and the familiar
function syntax would be used to specify the return type for switch
expressions. The “return” keyword could even be elided for single-line
cases as well, much like closures.

…oh, I just realized we’re on -users not -evolution here. Perhaps I’ll
bring this up next time switch expressions are proposed.

Nevin

···

On Sun, Nov 6, 2016 at 4:31 PM, Dave Abrahams via swift-users < swift-users@swift.org> wrote:

on Sun Nov 06 2016, Tino Heth <swift-users-AT-swift.org> wrote:

> Enums are a fundamental part of Swift, so I guess they won't change
> much — but I wonder if anyone shares my observations in real-life use…
>
> Afair, there are three different types of enums:
> - Enums with raw values
> - enums with associated objects
> - Plain enums (no underlying value)
>
> I use the first type quite often (as a convenient way to create string
> constants, or for serialization), but see no real value in plain enums
> (they offer nothing over enums backed with a raw value).
>
> The second type is special:
> It looks like a really cool concept, and and I started several designs
> based on them — just to realize later that structs and classes are a
> better fit.
> My conclusion so far is that enums perform bad as soon as you want to
> attach additional data or behavior; one or two computed properties are
> ok, but those switch-statements quickly become a burden.
> There are some options to work around this problem, but I guess I'll
> just stay away from enums with associated objects by default (with the
> exception of error-types — imho those can be modeled quite nicely).
>
> So, that's my current perception, and I'm curious if others had
> similar experiences — or, even more interesting, completely different
> observations and elegant solutions based on enums.

I have personally always found that exuberant use of that kind of enum
results in ergonomics and readability difficulties. There are several
things we have thought of that could potentially improve the situation,
most notably exposing each case as an optional property. I'd also
really like to see switch-expressions (as opposed to statements). I'm
not sure if that's really all we need in order to allow enums to reach
their potential, though.

--
-Dave

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Dave Abrahams) #6

Thanks :wink:

···

on Sun Nov 06 2016, Nevin Brackett-Rozinsky <nevin.brackettrozinsky-AT-gmail.com> wrote:

…oh, I just realized we’re on -users not -evolution here. Perhaps I’ll
bring this up next time switch expressions are proposed.

--
-Dave


(Tino) #7

…oh, I just realized we’re on -users not -evolution here.

:slight_smile: Core found an effective way to limit the distractions from evolution:
Over there, this would have been a proposal to remove enums [with associated objects] in favor of union types :wink:

Tino

Joking aside, imho it's a pity that all those fundamental discussions from the early times can't be published — I bet ideas like "everything is an expression" have been brought up, and the reason for their rejection could really help understanding the big picture of the language.