Extract Payload for enum cases having associated value

I apologise. I misunderstood the first time you asked me this.

Here is an example:


enum Foo {
    case baz(str: String)
    case baz(int: Int)
    case bla(int: Int)
    
    var label: String {
        return Mirror(reflecting: self).children.first?.label ?? String(describing: self)
    }
    
    func extractPayload<Payload>() -> Payload? {
        return decompose()?.payload
    }
    
    func extractPayload<Payload>(ifMatches pattern: (Payload) -> Foo) -> Payload? {
        guard let decomposed: (String, Payload) = decompose(),
            let patternLabel = Mirror(reflecting: pattern(decomposed.1)).children.first?.label,
            decomposed.0 == patternLabel else { return nil }
        
        return decomposed.1
    }
    
    private func decompose<Payload>() -> (label: String, payload: Payload)? {
        for case let (label?, value) in Mirror(reflecting: self).children {
            if let result = (value as? Payload) ?? (Mirror(reflecting: value).children.first?.value as? Payload) {
                return (label, result)
            }
        }
        return nil
    }
}

let intBaz = Foo.baz(int: 10)
let strBaz = Foo.baz(str: "baz")
let bla = Foo.bla(int: 20)

// indistinct extractPayload

let intBazValue: Int? = intBaz.extractPayload() // Optional(10)
let strBazValue: String? = strBaz.extractPayload() // Optional("baz")
let blaValue: Int? = bla.extractPayload() // Optional(20)

let all = [
    intBaz,
    strBaz,
    bla
]

let allStr: [String] = all.compactMap { $0.extractPayload() } // ["baz"]
let allInt: [Int] = all.compactMap { $0.extractPayload() } // [10, 20]

// pattern matching extraction

let intBazValue2 = intBaz.extractPayload(ifMatches: Foo.baz(int:)) //Optional(10)
let strBazValue2 = intBaz.extractPayload(ifMatches: Foo.baz(str:)) //Optional("baz")
let blaValue2 = bla.extractPayload(ifMatches: Foo.bla)// Optional(20)

let allRepeated = [
    intBaz,
    intBaz,
    intBaz,
    strBaz,
    strBaz,
    strBaz,
    bla
]

let allStrBaz = allRepeated.compactMap { $0.extractPayload(ifMatches: Foo.baz(str:)) } // ["baz", "baz", "baz"]
let allIntBaz: [Int] = allRepeated.compactMap { $0.extractPayload(ifMatches: Foo.baz(int:)) } // [10, 10, 10]

There are use cases for this choice. Consider an enum in which each case associated value is representing the same thing.

enum ItemUnion {
    case featuredImageItem(Item)
    case featuredTextItem(Item)
    case newArrivalsItem(Item)
    case imageItem(Item)
    case productItem(Item)
    case textItem(Item)
    case designersItem(Item)
    case shopsItem(Item)
    case videoItem(Item)
    case textOnlyPromoItem(Item)
    case imageWithTitleItem(Item)
    case individualSaleItem(Item)
    case feedProductItem(Item)
}

In this use case, there are areas of the app that might be interested in knowing the exact case and cases that can deal with Any Item indistinctly, hence the unconditioned extractPayload

While we can argue that the union can have a computed var, or that the whole thing can be wrote in a different way, the point of this pitch is to support this feature natively without requiring to write computed vars ourselves, and without giving these computed vars automatically to who doesn't want them