自定义 Swift 运算符中的通用类型操作数

Generic type operands in custom Swift operator

我的目标是创建一个可以让我轻松合并 Dictionary 值的运算符,例如:

["a" : "A"] + ["b" : "B"]

我的尝试如下:

extension Dictionary {
    public static func +=<K, V>(lhs: inout Dictionary<K, V>, rhs: Dictionary<K, V>?) {
        if let rhs = rhs {
            lhs.merge( rhs )
        }
    }

    public static func +=<K, V>(lhs: inout Dictionary<K, V>?, rhs: Dictionary<K, V>) {
        if var lhs = lhs {
            lhs.merge( rhs )
        }
        else {
            lhs = rhs
        }
    }

    public static func +<K, V>(lhs: Dictionary<K, V>, rhs: Dictionary<K, V>?) -> Dictionary<K, V> {
        if let rhs = rhs {
            return lhs.merging( rhs )
        }

        return lhs
    }

    public static func +<K, V>(lhs: Dictionary<K, V>?, rhs: Dictionary<K, V>) -> Dictionary<K, V> {
        if let lhs = lhs {
            return lhs.merging( rhs )
        }

        return rhs
    }

    @inlinable public mutating func merge(_ other: [Key: Value]) {
        self.merge( other, uniquingKeysWith: {  } )
    }

    @inlinable public func merging(_ other: [Key: Value]) -> [Key: Value] {
        self.merging( other, uniquingKeysWith: {  } )
    }
}

这似乎不起作用(从 Swift 5 开始),我怀疑这个问题与 Dictionary 类型是通用类型有关。任何人都可以解释是什么阻碍了它的工作以及是否有替代方案 solution/approach 可以工作?

问题在于您正在创建新的通用 KV 值类型。您所需要做的就是在您的方法声明中省略它们。顺便说一句,你忘了添加一个方法来总结两个非可选字典:

extension Dictionary {

    public static func +=(lhs: inout Dictionary, rhs: Dictionary) {
         lhs.merge(rhs)
    }
    public static func +=(lhs: inout Dictionary, rhs: Dictionary?) {
        if let rhs = rhs { lhs.merge(rhs) }
    }
    public static func +=(lhs: inout Dictionary?, rhs: Dictionary) {
        if var lhs = lhs { lhs.merge(rhs) } else { lhs = rhs }
    }

    public static func +(lhs: Dictionary, rhs: Dictionary) -> Dictionary {
        lhs.merging(rhs)
    }
    public static func +(lhs: Dictionary, rhs: Dictionary?) -> Dictionary {
        if let rhs = rhs { return lhs.merging(rhs) }
        return lhs
    }
    public static func +(lhs: Dictionary?, rhs: Dictionary) -> Dictionary {
        if let lhs = lhs { return lhs.merging(rhs) }
        return rhs
    }

    @inlinable public mutating func merge(_ other: Dictionary) {
        self.merge(other) {}
    }

    @inlinable public func merging(_ other: Dictionary) -> Dictionary {
        self.merging(other) {}
    }
}

let dicSum = ["a" : "A"] + ["b" : "B"]

dicSum  // ["b": "B", "a": "A"]

另一种方法是为 Dictionary 通用键和值类型创建类型别名,并删除您在方法声明中创建的那些 <K,V> 否则它们将再次成为与 Dictionary 中定义的类型无关的新通用类型declaration:

extension Dictionary {

    public typealias K = Key
    public typealias V = Value

    public static func +=(lhs: inout [K: V], rhs: [K: V]) {
         lhs.merge(rhs)
    }
    public static func +=(lhs: inout [K: V], rhs: [K: V]?) {
        if let rhs = rhs { lhs.merge(rhs) }
    }
    public static func +=(lhs: inout [K: V]?, rhs: [K: V]) {
        if var lhs = lhs { lhs.merge(rhs) } else { lhs = rhs }
    }

    public static func +(lhs: [K: V], rhs: [K: V]) -> [K: V] {
        lhs.merging(rhs)
    }
    public static func +(lhs: [K: V], rhs: [K: V]?) -> [K: V] {
        if let rhs = rhs { return lhs.merging(rhs) }
        return lhs
    }
    public static func +(lhs: [K: V]?, rhs: [K: V]) -> [K: V] {
        if let lhs = lhs { return lhs.merging(rhs) }
        return rhs
    }

    @inlinable public mutating func merge(_ other: [K: V]) {
        self.merge(other) {}
    }

    @inlinable public func merging(_ other: [K: V]) -> [K: V] {
        self.merging(other) {}
    }
}

这与上面所做的完全相同。


同样 DictionaryDictionary<Key, Value>[Key:Value] 完全相同:

extension Dictionary {

    public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]) {
         lhs.merge(rhs)
    }
    public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]?) {
        if let rhs = rhs { lhs.merge(rhs) }
    }
    public static func +=(lhs: inout [Key: Value]?, rhs: [Key: Value]) {
        if var lhs = lhs { lhs.merge(rhs) } else { lhs = rhs }
    }

    public static func +(lhs: [Key: Value], rhs: [Key: Value]) -> [Key: Value] {
        lhs.merging(rhs)
    }
    public static func +(lhs: [Key: Value], rhs: [Key: Value]?) -> [Key: Value] {
        if let rhs = rhs { return lhs.merging(rhs) }
        return lhs
    }
    public static func +(lhs: [Key: Value]?, rhs: [Key: Value]) -> [Key: Value] {
        if let lhs = lhs { return lhs.merging(rhs) }
        return rhs
    }

    @inlinable public mutating func merge(_ other: [Key: Value]) {
        self.merge(other) {}
    }

    @inlinable public func merging(_ other: [Key: Value]) -> [Key: Value] {
        self.merging(other) {}
    }
}

所有 3 种实现方式都是等价的。选择一个你觉得舒服的。