自定义 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 可以工作?
问题在于您正在创建新的通用 K
、V
值类型。您所需要做的就是在您的方法声明中省略它们。顺便说一句,你忘了添加一个方法来总结两个非可选字典:
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) {}
}
}
这与上面所做的完全相同。
同样 Dictionary
、Dictionary<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 种实现方式都是等价的。选择一个你觉得舒服的。
我的目标是创建一个可以让我轻松合并 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 可以工作?
问题在于您正在创建新的通用 K
、V
值类型。您所需要做的就是在您的方法声明中省略它们。顺便说一句,你忘了添加一个方法来总结两个非可选字典:
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) {}
}
}
这与上面所做的完全相同。
同样 Dictionary
、Dictionary<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 种实现方式都是等价的。选择一个你觉得舒服的。