[swift-evolution] Proposal: Add replace(_:with:) function to the stdlib

Kevin Ballard kevin at sb.org
Sun Jan 10 19:43:58 CST 2016

On Sun, Jan 10, 2016, at 04:30 PM, Brent Royal-Gordon wrote:
> One thing I noticed is that this appears to be a generalization of `Dictionary.updateValue(_:forKey:)`. Should the dictionary-specific version continue to exist? If it should, should we modify one or the other to have more closely-matching naming or argument ordering?

Good question. I'm inclined to say that we should keep Dictionary.updateValue(_:forKey:) for two reasons:

1. Documentation. It's reasonable to expect a function like Dictionary.updateValue(_:forKey:) to be found on Dictionary.
2. Performance. Dictionary's getter/setter combo is implemented using a classic computed getter/setter pair (as opposed to mutableAddressWithPinnedNativeOwner), which makes sense because adding or deleting keys need to do more than manipulate the contents of an address. But because of this, using an inout expression &d[key] actually invokes the getter, performs the mutations, and then invokes the setter with the new value. This means that the expression `replace(&d[key], with: newValue)` actually looks up the key in the hashtable twice, whereas Dictionary.updateValue(_:forKey:) only has to look it up once.

I don't think it makes sense to swap the arguments for replace(_:with:). We could change updateValue(_:forKey:) to instead be called something like updateKey(_:withValue:), but the current name updateValue(_:forKey:) is consistent with the method removeValueForKey(_:).

So ultimately, while I recognize that `replace(&d[key], with: newValue)` is equivalent to `d.updateValue(newValue, forKey: key)` (though likely with slightly worse performance), I think we should keep both replace(_:with:) and Dictionary.updateValue(_:forKey:) as-is.

-Kevin Ballard

More information about the swift-evolution mailing list