To go along with the recently reviewed Derived Collection of Enum Cases, I'd like to propose that we also derive a Case enum for all enums.
The problem
One of the biggest issues I have with using enums is that comparing the case of two enums is really painful. Take for example, if I decided to make a game called Orc vs Elves vs Humans, and decided to represent them as an enum
enum Race {
case orc(weapon: Weapon)
case elf(spell: MagicSpell)
case human(karateMove: KarateMove)
func attack(race: Race) {}
}
Now lets say that there's a crazy wizard, who every 30 seconds casts a spell that makes a random one of these races invincible. Unfortunately, right now in Swift there's not really a clean way to do it. How do I store which of these races is the currently invincible one?
Pitch
Can we auto-synthesize an internal Case enum inside of enums to represent the case and expose that via a case var? For example:
enum Race {
case orc(weapon: Weapon)
case elf(spell: MagicSpell)
case human(karateMove: KarateMove)
func attack(race: Race) {}
/// AUTO-SYNTHESIZED
enum Case {
case orc
case elf
case human
}
// AUTO-SYNTHESIZED
var `case`: Case {
switch self {
case .orc:
return .orc
case .elf:
return .elf
case human:
return .human
}
}
}
That would solve our above problem because we could use:
var invincibleRace: Race.Case
and for checking if we can attack it?
func attack(race: Race) {
guard race.case != invincibleRace else { return }
doDamage()
}
It would also make it possible to compare the case of two enums, which is currently super painful. Say we have:
let a = Race.orc(weapon: Sword())
let b = Race.elf(spell: Fireball())
This is what we have to do now:
switch(a, b) {
case (.orc, .orc):
return true
case (.elf, .elf):
return true
case (.human, .human):
return true
default:
return false
}
}
This is what it would look like with the synthesized case:
return a.case == b.case
I've been using sourcery to autogenerate these already, but it's worked well enough that I think it's worth considering for Swift itself.