Grant Emerson

Keying Into Tuples

Keying Into Tuples — SwiftMoji Entry #1

In the release of Swift 5.1, KeyPaths gained support for accessing the elements within a tuple. In the code example below, an array of WritableKeyPaths as passed into a remove(:) function on the HotDog struct. Due to the inherent relationship between chili, cheese, and tomatoes as condiments, they are grouped in a tuple. This avoids the hassle of nesting an additional struct within the HotDog type. Previous to Swift 5.1, this would prevent the users of the remove(:) function from accessing all the ingredients within HotDog. However, now, with recent enhancements, a Person is no longer limited to the ingredients they wish to leave off their HotDog.

struct HotDog {
    var bun: String?
    var meat: String?
    var condiments: (chili: String?, cheese: String?, tomatoes: String?)
    
    var ingredients: String {
        [bun, meat, condiments.chili, condiments.cheese, condiments.tomatoes]
            .compactMap { $0 }
            .joined(separator: ", ")
    }
    
    mutating func remove(_ ingredients: Set<WritableKeyPath<Self, String?>>) {
        ingredients.forEach { self[keyPath: $0] = nil }
    }
}

struct Person {
    let name: String
    let dislikedIngredients: Set<WritableKeyPath<HotDog, String?>>
}

var 🌭 = HotDog(bun: "🥖", meat: "🦃",
                condiments: (chili: "🌶", cheese: "🧀", tomatoes: "🍅"))

let 👨‍🍳 = Person(
    name: "Timothy",
    dislikedIngredients: [
        \HotDog.condiments.chili,
        \HotDog.condiments.tomatoes
    ]
)

🌭.remove(👨‍🍳.dislikedIngredients)
print("👨‍🍳's 🌭 has: \(🌭.ingredients)")
Tagged with: