Swift: Extension on [?] to produce [?] possible?

前端 未结 2 609
傲寒
傲寒 2021-01-13 02:44

In Swift, I have a custom struct with this basic premise:

A wrapper struct that can contain any type that conforms to BinaryInteger suc

相关标签:
2条回答
  • 2021-01-13 03:26

    Martin R's answer is a good solution. An alternative that doesn't require an extra marker protocol is this: write an unconstrained extension on Collection, and in that extension, define a generic function that's constrained to where Element == SomeType<T>?:

    extension Collection {
        func values<T>() -> [T?] where Element == SomeType<T>? {
            return map( { $0?.value })
        }
    }
    

    This works:

    let arr: [SomeType<Int>?] = [SomeType(value: 123), SomeType(value: 456)]
    arr.values() // [Optional(123), Optional(456)]
    

    You'll notice that I used a func instead of a computed property. I couldn't get the generic syntax right. Isn't this supposed to work?

    extension Collection {
        // error: consecutive declarations on a line must be separated by ';'
        var values<T>: [T?] where Element == SomeType<T>? {
            return self.map( { $0?.value })
        }
    }
    
    0 讨论(0)
  • 2021-01-13 03:32

    I don't know if there is a simpler solution now, but you can use the same “trick” as in How can I write a function that will unwrap a generic property in swift assuming it is an optional type? and Creating an extension to filter nils from an Array in Swift, the idea goes back to this Apple Forum Thread.

    First define a protocol to which all optionals conform:

    protocol OptionalType {
        associatedtype Wrapped
        var asOptional: Wrapped? { get }
    }
    
    extension Optional : OptionalType {  
        var asOptional: Wrapped? {  
            return self 
        }  
    }  
    

    Now the desired extension can be defined as

    extension Collection where Element: OptionalType, Element.Wrapped: SomeTypeProtocol {
        var values: [Element.Wrapped.NumberType?] {
            return self.map( { $0.asOptional?.value })
        }
    }
    

    and that works as expected:

    let arr = [SomeType(value: 123), nil, SomeType(value: 456)]
    let v = arr.values
    
    print(v) // [Optional(123), Optional(456)]
    print(type(of: v)) // Array<Optional<Int>>
    
    0 讨论(0)
提交回复
热议问题