Last week we concluded an introduction to the concept of “case paths”. It’s a tool that lets you generically isolate a single case of an enum from the rest of the cases. We were inspired to create this tool because we saw just how handy key paths are, and how they allow us to write generic algorithms that can pick apart and reassemble structs, and it stands to reason that such a thing would be really nice for enums too.
And in fact, we have a great use case for that already in the Composable Architecture. When we wanted to modularize our reducers, so that a reducer could work on just the domain it cared about while still allowing itself to be plugged into the global domain, we were naturally led to the pullback
operation. It lets you take a reducer that works on a local domain and pull it back to work on the global domain. And then you can take a whole bunch of these little reducers and combine them together into one big ole reducer that powers your entire application.
In order to define this pullback
operation we used key paths, and it was a great example of how you can write generic algorithms that abstract over the shape of data. We could use the key paths to pluck out the pieces of a data structure we care about, run the reducer on those smaller parts, and then use the key path again to glue everything back together.
However, our usage of key paths for the action of the reducer was a little strange. Perhaps the most glaring issue was that we had to turn to code generation to even get access to the key path. Fortunately, all of the work we did for case paths is applicable to the Composable Architecture, and it will simultaneously simplify our pullback
operation and get rid of all of the code generation.
It may sound too good to be true, but it is true. But before we get to that, let’s take a quick trip down memory lane to see what our app looks like and a brief overview of how we built it.