Enum Properties

Episode #52 • Apr 1, 2019 • Subscriber-Only

Swift makes it easy for us to access the data inside a struct via dot-syntax and key-paths, but enums are provided no such affordances. This week we correct that deficiency by defining the concept of “enum properties”, which will give us an expressive way to dive deep into the data inside our enums.

Previous episode
Enum Properties
Introduction
00:05
Accessing product and sum data
01:24
Arrays of enums
06:52
Structs and key paths
11:45
Accessing Result data
13:29
Recovering enum ergonomics
17:09
What’s the point?
22:06

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Introduction

Last time we revisited a topic that we know and love: algebraic data types. We explored how in the Swift type system Swift, multiplication manifests itself in product types, like structs and tuples, and addition manifests itself in sum types, like enums. We saw that, just like in algebra, addition and multiplication, and structs and enums are just two sides of the same coin: no one is more important than the other. And we saw that many of the things we love about structs do in fact have a corresponding feature on enums, and vice versa.

However, we also saw that product types definitely see some favoritism over enums in the language design. We saw this especially in how Swift gives us anonymous structs in the form of tuples, but there is no corresponding anonymous enum type. We theorized how it might look and we may even have it in the language some day because it’d be a really nice tool to have.

Now anonymous sum types isn’t something we can fix ourselves, but there are other examples of struct favoritism that we can correct by bringing enums up to the same level.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in

Exercises

  1. While we’ve defined the gets of our enum properties, we haven’t defined our sets. Redefine Validated’s valid and invalid properties to have a setter in addition to its getter.

    Solution

    We can redefine valid with the following setter.

    var valid: Valid? {
      get {
        guard
          case let .valid(value) = self
          else { return nil }
        return value
      }
      set {
        guard
          let newValue = newValue,
          case .valid = self
          else { return }
        self = .valid(newValue)
      }
    }
    

    While we must safely unwrap a non-optional newValue to reassign self, we also test that the current self is valid before doing so.

    The invalid property is the same boilerplate but uses the invalid case.

    var invalid: [Invalid]? {
      get {
        guard
          case let .invalid(value) = self
          else { return nil }
        return value
      }
      set {
        guard
          let newValue = newValue,
          case .invalid = self
          else { return }
        self = .invalid(newValue)
      }
    }
    
  2. Take the valid setter for a spin. Assign Validated<Int, String>.valid(1) to a variable and increment the number using the setter.

    Solution

    There are a few ways of doing this! First, let’s assign a mutable variable.

    var v = Validated<Int, String>.valid(1)
    

    We can map over the optional Int returned by the valid getter.

    v.valid = v.valid.map { $0 + 1 }
    

    Or we can optionally chain with the += operator.

    v.valid? += 1
    

References

Getters and Key Paths

Brandon Williams & Stephen Celis • Monday Mar 19, 2018

An episode dedicated to property access on structs and how key paths can further aid us in writing expressive code.

Key paths aren’t just for setting. They also assist in getting values inside nested structures in a composable way. This can be powerful, allowing us to make the Swift standard library more expressive with no boilerplate.

SE-0249: Key Path Expressions as Functions

Stephen Celis & Greg Titus • Tuesday Mar 19, 2019

A proposal has been accepted in the Swift evolution process that would allow key paths to be automatically promoted to getter functions. This would allow using key paths in much the same way you would use functions, but perhaps more succinctly: users.map(\.name).

How Do I Write If Case Let in Swift?

Zoë Smith

This site is a cheat sheet for if case let syntax in Swift, which can be seriously complicated.

Downloads