In Scala, the + (k -> v)
operator on immutable.Map
returns a new immutable.Map
with the contents of the original, plus the new key/value pair. Similarly, in C#, ImmutableDictionary.add(k, v)
returns a new, updated ImmutableDictionary
.
In Swift, however, Dictionary
appears only to have the mutating updateValue(v, forKey: k)
function and the mutating [k:v]
operator.
I thought maybe I could play some trick with flatten()
, but no luck:
let updated = [original, [newKey: newValue]].flatten()
gets me
Cannot convert value of type '() -> FlattenCollection<[[String : AnyObject]]>'
to specified type '[String : AnyObject]'
How do I create a new, modified immutable Dictionary
from the contents of an existing one?
Update: Based on this answer's note that Swift dictionaries are value types, and this answer's mutable version, I came up with the following extension operator, but I'm not excited about it -- it seems like there must be a cleaner out-of-the-box alternative.
func + <K, V>(left: [K:V], right: [K:V]) -> [K:V] {
var union = left
for (k, v) in right {
union[k] = v
}
return union
}
But maybe the fact (if I understand correctly) that the immutability of Swift dictionaries is a compiler check on let
rather than a matter of different implementation classes means this is the best that can be done?
Update #2: As noted in Jules's answer, modifying immutable dictionaries that aren't specifically optimized to share state between copies (as Swift dictionaries aren't) presents performance problems. For my current use case (AttributedString
attribute dictionaries, which tend to be fairly small) it may still simplify certain things enough to be worth doing, but until and unless Swift implements a shared-state immutable dictionary it's probably not a good idea in the general case -- which is a good reason not to have it as a built-in feature.