Swift Conditional Conformance with Any

后端 未结 2 1131
小鲜肉
小鲜肉 2021-01-27 05:03

Let\'s assume an array of Result. We want the array to be reduced to a Result of an array. For example:

let z: [Result         


        
相关标签:
2条回答
  • 2021-01-27 05:20

    You can create a generic method and remove the constraint from the extension:

    extension Sequence {
        func reduced<T>() -> Result<[T], Error> where Element == Result<T, Error> {
            reduce(.success([])) {
                switch $0 {
                case .failure: return $0
                case let .success(array):
                    switch $1 {
                    case let .failure(error): return .failure(error)
                    case let .success(value): return .success(array + CollectionOfOne(value))
                    }
                }
            }
        }
    }
    

    Btw you can also use a plain loop and provide an early exit at the first failure:

    extension Sequence {
        func reduced<T>() -> Result<[T], Error> where Element == Result<T, Error> {
            var array: [T] = []
            for result in self {
                switch result {
                case let .failure(error): return .failure(error)
                case let .success(value): array.append(value)
                }
            }
            return .success(array)
        }
    }
    

    A more concise approach would be to create a generic method that throws or return an array with all successes:

    extension Sequence {
        func successes<T, E>() throws -> [T] where Element == Result<T, E>, E: Error {
            try map { try $0.get() }
        }
    }
    

    Playground testing:

    let z: [Result<Int, MyError>] = [.success(1),
                                   .success(2),
                                   .success(3)] //,
                                   //.failure(.blah)]
    do {
        let successes = try z.successes()
        print(successes)  // [1, 2, 3]
    } catch {
        print(error)
    }
    
    0 讨论(0)
  • 2021-01-27 05:34

    You can move constraints to the function to make it generic:

    extension Array {
        func reduced<T>() -> Result<[T], Error> where Element == Result<T, Error> {
            return self.reduce(.success([T]())) { accumulator, result in
                ...
            }
        }
    }
    

    Note: A variable of type Int will not match Any as it's a different type. Variables of type Any need to be casted down to Int.

    0 讨论(0)
提交回复
热议问题