We have explored the idea that Swift’s structs and enums are intimately and fundamentally related to each other in many past Point-Free episodes. We first did this in our episodes on algebraic data types, where we showed that in a very precise sense enums correspond to addition that we all know and love from algebra, and structs correspond to multiplication. We even showed that certain algebraic properties also carry over to Swift, like the fact that multiplication distributes over addition means that you can refactor your own data types to factor out common pieces of data.
We took this idea even further in another episode where we claimed that literally any feature you endow structs with there should be a corresponding version of it for enums, and vice versa. There are a few examples of where this principle holds, or mostly holds, for various features of structs and enums. However, in general this is not the case, and there are many instances where Swift clearly favors structs over enums where Swift gives structs many features that enums do not get.
One particular example we looked at was how ergonomic it is to access the data inside a struct. One can simply use dot syntax to get and set any field inside a struct value. The same is not true of enums, you have no choice but to do a switch
, if case let
or guard case let
, which are syntactically heavy when all you wanna do is access a little bit of data inside an enum.
This led us down the path of defining what we called “enum properties”, which give enums the power of accessing their data with simple dot-syntax just like structs. We even created a code generation tool (part 1, part 2, part 3), using Apple’s Swift Syntax library, to automatically generate these properties for us to make it as easy as possible.
We want to take that work even further and discuss another feature that Swift structs are blessed with but which sadly has no representation for enums, and that is key paths. Key paths are a powerful feature in Swift, and we’ve talked about and used them a ton on Point-Free. Every field on a struct magically gets a key path generated for it by the compiler. But what does the corresponding concept look like when applied to enums? Answering this question will give us a tool for unlocking even more power from enums, and will even help us greatly simplify some code we previously wrote for the composable architecture.
Let’s start by reminding ourselves what key paths are and why they are so powerful.