# Polymorphic methods in enums

**URL:** <https://forums.swift.org/t/polymorphic-methods-in-enums/15093>\
**Category:** Pitches\
**Created:** [August 8, 2018, 1:13pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093 "2018-08-08T13:13:57Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![pgb](https://avatars.discourse-cdn.com/v4/letter/p/e9a140/32.png) [@pgb](https://forums.swift.org/u/pgb)\
**Post date:** [August 8, 2018, 1:13pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/1 "2018-08-08T13:13:57Z")

</div>

Since I started using Swift, I've been drawn to `enums` for their features (associated values, type safety, etc.)

However, I noticed that in doing so, I lost some polymorphism. Consider the traffic light enum:

```
enum TrafficLight {
    case green
    case yellow
    case red
}

```

Let's say I want to add a `canAdvance` function, I'll end up with something like this (discussing if advancing in yellow is fine is out of the scope ;) )

```
enum TrafficLight {
    case green
    case yellow
    case red

    func canAdvance() -> Bool {
        switch self {
            case .green:
                return true
            case .yellow, .red:
                return false
        }
    }
}

```

This works, but if your enum grows and needs more methods, we end up with a switch within each method.

What I'd love to see is a way to remove those switches, that can enable tidier code. I'm thinking on something like this:

```
enum TrafficLight {
    case green
    case yellow
    case red

    func canAdvance() -> Bool {
        return false
    }
}

extension TrafficLight where case .green {
    func canAdvance() -> Bool {
        return true
    }
}

```

This would enable extensions on enums for each different case.

I don't know if this is easy (or even possible) to implement, plus, this is my first time writing on the forum, so any comments are welcome.

---

<div class="post-metadata">

**Author:** ![griotspeak](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/griotspeak/32/1966_2.png) [@griotspeak](https://forums.swift.org/u/griotspeak)\
**Post date:** [August 8, 2018, 2:20pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/2 "2018-08-08T14:20:26Z")

</div>

```swift
extension TrafficLight {
    func canAdvance() -> Bool {
        if case .green = self {
            return true
        } else {
            return false
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![antonthehuman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/antonthehuman/32/3356_2.png) [@antonthehuman](https://forums.swift.org/u/antonthehuman)\
**Post date:** [August 8, 2018, 2:43pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/3 "2018-08-08T14:43:07Z")

</div>

Sounds like constant expressions in generic where clause.

> <https://github.com/apple/swift/blob/main/docs/GenericsManifesto.md#generic-value-parameters>

> [@Compile-Time Constant Expressions for Swift](https://forums.swift.org/t/compile-time-constant-expressions-for-swift/12879):
>
> Chris Lattner and I have been working on a proposal to add compile-time constant expressions to Swift. Our goal is to create a very general feature that enables many other useful features that need compile-time execution, like: static assertions, value parameters in generics, some TensorFlow operations in Swift for TensorFlow, and more (see the motivation section of the draft proposal for a detailed discussion). We would like your feedback on our draft proposal! The draft proposal is here, and…

Also what about associated values?

---

<div class="post-metadata">

**Author:** ![pgb](https://avatars.discourse-cdn.com/v4/letter/p/e9a140/32.png) [@pgb](https://forums.swift.org/u/pgb)\
**Post date:** [August 8, 2018, 2:50pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/4 "2018-08-08T14:50:39Z")

</div>

I'm not sure how would I manage the syntax, but I guess we can access the associated value in the extension.

Maybe declaring the variable name in the same `where` clause, just as you do in `if case`.

---

<div class="post-metadata">

**Author:** ![griotspeak](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/griotspeak/32/1966_2.png) [@griotspeak](https://forums.swift.org/u/griotspeak)\
**Post date:** [August 8, 2018, 3:26pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/5 "2018-08-08T15:26:38Z")

</div>

This proposal doesn't seem related to the original post. Compile time constant expressions, as far as I can tell, don't do much for extension parameters. That comes closer to having values at the type level, which has been discussed, but is not that proposal.

---

<div class="post-metadata">

**Author:** ![gwendal.roue](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gwendal.roue/32/13992_2.png) [@gwendal.roue](https://forums.swift.org/u/gwendal.roue)\
**Post date:** [August 8, 2018, 3:39pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/6 "2018-08-08T15:39:23Z")

</div>

Swift already provides polymorphism with classes and protocols. I don't know if enums will eventually enter this dance, too.

What I know is that you're not the only one who faces this dilemma: as a code base grows, the limitations of initial design choices start to appear. Swift has a few traps like that. Strengthening one's intuition on this matter is an acquired skill. Discussing those issues is important so that the community gets a large feedback on eventual language caveats. Finding which ones should be solved, and how, is another question ;-)

For the record, refactoring your particular case around protocols could give something along:

```swift
// What is a TrafficLight?
protocol TrafficLight {
    // customization point
    var canAdvance: Bool { get }
}
extension TrafficLight {
    // default value
    var canAdvance: Bool { return false }
}

// Three particular traffic lights
struct GreenLight: TrafficLight { var canAdvance: Bool { return true } }
struct OrangeLight: TrafficLight {}
struct RedLight: TrafficLight {}

// Using traffic lights
func handle(_ trafficLight: TrafficLight) {
    if trafficLight.canAdvance {
        print("drive")
    } else {
        print("wait")
    }
}

handle(GreenLight()) // drive
handle(OrangeLight()) // wait

```

---

<div class="post-metadata">

**Author:** ![pgb](https://avatars.discourse-cdn.com/v4/letter/p/e9a140/32.png) [@pgb](https://forums.swift.org/u/pgb)\
**Post date:** [August 8, 2018, 4:39pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/7 "2018-08-08T16:39:21Z")

</div>

This refactoring is how I usually handle it. But given that Swift affords us great `enum`s, extending them to support this seemed like a good idea.

---

<div class="post-metadata">

**Author:** ![nuclearace](https://avatars.discourse-cdn.com/v4/letter/n/51bf81/32.png) [@nuclearace](https://forums.swift.org/u/nuclearace)\
**Post date:** [August 8, 2018, 6:57pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/8 "2018-08-08T18:57:05Z")

</div>

This kind of feature reminds me of functional languages that allow you to provide different implementations depending on the runtime value of some parameter.

For example elixir:

```nohighlight
  def changeset(%User{} = user, %{"password" => pw} = attrs) when pw != "" do
    attrs = %{attrs | "password" => Bcrypt.hashpwsalt(pw)}

    user
    |> cast(attrs, [:firstname, :lastname, :username, :password])
    |> validate_required([:firstname, :lastname, :username, :password])
    |> unique_constraint(:username)
  end

  def changeset(%User{} = user, attrs) do
    user
    |> cast(attrs, [:firstname, :lastname, :username, :password])
    |> validate_required([:firstname, :lastname, :username, :password])
    |> unique_constraint(:username)
  end

```

or Haskell

```nohighlight
factorial 0 = 1
factorial n = n * factorial (n - 1)

```

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [August 8, 2018, 6:58pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/9 "2018-08-08T18:58:59Z")

</div>

Those features are almost always just sugar for a `switch`, but I agree that they're awfully convenient anyway.

---

<div class="post-metadata">

**Author:** ![nuclearace](https://avatars.discourse-cdn.com/v4/letter/n/51bf81/32.png) [@nuclearace](https://forums.swift.org/u/nuclearace)\
**Post date:** [August 8, 2018, 7:18pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/10 "2018-08-08T19:18:32Z")

</div>

I wonder if this kind of feature would be feasible to add given the existing space engine for exhaustiveness checking if all this would be is a sugar for a single implementation with a switch deciding the body.

---

<div class="post-metadata">

**Author:** ![hlovatt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hlovatt/32/3044_2.png) [@hlovatt](https://forums.swift.org/u/hlovatt)\
**Post date:** [August 8, 2018, 8:44pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/11 "2018-08-08T20:44:34Z")

</div>

Most of the JVM languages, Java/Scala/Kotlin, allow this. It is a feature I mis from these languages. In these languages each case of the enum is a seperate type with its own dispatch table. You can mimic this behaviour in Swift with a protocol for the enum and a struct implementing the protocol for each case but then you can’t then stop people adding new cases.

The Java syntax would probably work in Swift:

```swift
enum TrafficLight {
    case green {
        func canAdvance() -> Bool { return true }
    }
    case yellow {
        func canAdvance() -> Bool { return true }
    }
    case red {
        func canAdvance() -> Bool { return false }
    }

    func canAdvance() -> Bool // Same syntax as declaring a func in a protocol. 
}

```

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [August 8, 2018, 8:55pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/12 "2018-08-08T20:55:37Z")

</div>

See, this bit I don't get. That's _more_ verbose than using a switch.

EDIT: I too think the current language feature is a little clunky. I just haven't seen anything _less_ clunky yet.

---

<div class="post-metadata">

**Author:** ![pgb](https://avatars.discourse-cdn.com/v4/letter/p/e9a140/32.png) [@pgb](https://forums.swift.org/u/pgb)\
**Post date:** [August 8, 2018, 8:57pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/13 "2018-08-08T20:57:49Z")

</div>

I think it depends on the number of cases the `enum` has, and the number of methods in there.

I agree that the syntax plays a big role in how readable is.

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [August 8, 2018, 8:58pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/14 "2018-08-08T20:58:27Z")

</div>

It also doesn't work with unlabeled associated values, unfortunately. How would I refer to the integer in this example:

```swift
enum Foo {
  case bar(Int) {
    func someFunction() -> Int {
      return ???
    }
  }
}

```

We'd have to do something like graft in closure shorthand variables (`$0`?) or invent some other syntax for it.

But I agree with @jrose; every time I've thought of this problem, I haven't been able to figure out a sweet spot that doesn't just feel like shuffling the deck chairs while providing a concrete benefit.

---

<div class="post-metadata">

**Author:** ![nuclearace](https://avatars.discourse-cdn.com/v4/letter/n/51bf81/32.png) [@nuclearace](https://forums.swift.org/u/nuclearace)\
**Post date:** [August 8, 2018, 9:04pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/15 "2018-08-08T21:04:35Z")

</div>

This could be solved with a generalization of this to all functions.

```swift
enum Color {
  case red
  case green
  case blue
  case other(Int, Int, Int)

  func something() when self = .other(50, g, b) {
  }

  func something() when self = .other(r, g, b) {
  }

  func something() { } // everything else
}

```

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [August 8, 2018, 9:07pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/16 "2018-08-08T21:07:42Z")

</div>

Agreed about none of the alternatives seeming like improvements. Haskell's syntax for this is elegant, but it works because (1) the type signature is written separately and (2) the switched-on parameters are all explicit and so can be easily pattern-ized. In other words, it works because there's already some verbosity that people take for granted.

I wonder how much of the clunkiness here is just the extra level of bracing required. Like if you had:

```swift
func canAdvance() -> Int = switch { // implicitly over self
  case .green: return true
  default: return false
}

```

---

<div class="post-metadata">

**Author:** ![nuclearace](https://avatars.discourse-cdn.com/v4/letter/n/51bf81/32.png) [@nuclearace](https://forums.swift.org/u/nuclearace)\
**Post date:** [August 8, 2018, 9:15pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/17 "2018-08-08T21:15:20Z")

</div>

From my experience, this would help a bit. Most enum methods I've written are generally very short, and very commonly a mapping between things. The biggest worry I have is it would erode some notions that statements in Swift aren't expressions. It begins to look like syntax you'd find in languages where this is the case.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [August 8, 2018, 9:16pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/18 "2018-08-08T21:16:36Z")

</div>

Another riff on this general idea, maybe we could allow top-level `case` labels in function bodies:

```swift
func foo(x: A, y: B) -> String? {
case (x: .foo, y: .bar):
  return "foo bar"
case (x: .zim, y: .zang):
  return "zim zang"
default:
  return nil
}

```

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [August 8, 2018, 9:21pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/19 "2018-08-08T21:21:47Z")

</div>

Hmm. Is that implicitly switching over all the non-`self` arguments packaged up as a tuple?

Implicitly switching over just `self` makes sense to me in an instance method. That's very analogous to the sorts of sugar used in other languages.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [August 8, 2018, 9:23pm UTC](https://forums.swift.org/t/polymorphic-methods-in-enums/15093/20 "2018-08-08T21:23:47Z")

</div>

Sure, maybe only implicitly switching over `self` makes more sense. If there's an elegant syntax to allow matching either `self` or other arguments or some combination thereof that might be nice.

[Next page](https://forums.swift.org/t/polymorphic-methods-in-enums/15093.md?page=2)
