我试图编写一个函数来深度合并两个词典。我的意思是,当两个字典中的键的值被合并并且这些值都是字典时,它们将被合并而不是被另一个替换。
以下是我所拥有的:
extension Dictionary {
public func deepMerged(with other: [Key: Value]) -> [Key: Value] {
var result: [Key: Value] = self
for (key, value) in other {
if let value = value as? [Key: Value], let existing = result[key] as? [Key: Value] {
result[key] = existing.deepMerged(with: value)
} else {
result[key] = value
}
}
return result
}
}
但不幸的是它没有编译。我收到了错误
无法转换类型的值' [Key:Value]'预期参数类型[_:_]'关于在`deepMerged(with :)中的递归调用中使用值。
我能够通过确定扩展名来解决这个问题:
extension Dictionary where Key == String, Value == Any {
...
}
这适用于我此时的特定用例,但我不明白为什么更通用的代码无效。
答案 0 :(得分:3)
请注意,错误发生在result[key]
的分配上,而不是函数调用本身:
let merged: [Key:Value] = existing.deepMerged(with: value) //works fine
result[key] = merged //error
编译器知道:
result
是[Key: Value]
other
是[Key: Value]
key
是Key
value
是Value
merged
是[Key:Value]
result
有subscript(key: Key) -> Value? { get set }
(即Value?
类型的可写下标,可接受Key
)但不知道[Key:Value]
是Value
,因此它不知道merged
可以传递给{{1}的下标}}。由于result
是value
且Value
也是value
,我们知道[Key: Value]
必须是[Key: Value]
,但编译器不知道这一点。
解决方案是将Value
投射到merged
:
Value