Just to clarify: It seems like the only ABI-affecting change here is the type 
of keys/values. As you note at the end of your proposal, this should just be 
Dictionary.Keys/Dictionary.Values regardless of whether we implement this 
proposal or not, in which case this can be punted for Swift 4. It should be 
fine to keep .Keys/.Values resilient so that we can change their implementation 
details later if we want.

On the actual proposal: this is a pretty reasonable given Swift’s current 
design and constraints. That said, I expect pushing forward on this kind of 
thing right now is premature given the goals of Swift 4. A major aspect of 
Swift 4 is reworking the way CoW semantics function internally, which could 
drastically affect the way we approach this problem.

I’d really like if we could eliminate the “double search/hash” in the 
no-existing-key case. There are ways to do this really cleanly, but they 
probably involve more advanced CoW-safety propagation. In particular, you want 
some way for the collection to return its search state to the caller so that 
they can hand it back to insertion to just resume from there.

For instance:

map.entries[key]           // An enum like Found(Value) | NotFound(SearchState)
   .withDefault(value: []) // Unwrap the enum by completing the 
   .append(1)              // Now we have a value in both cases, we can append!

Or more complex:

   .withDefault { /* logic that computes value */ }

I think this can be made to work in the current system if withDefault is 
actually `[withDefault:]`, which is fine but a bit weird from a user’s 

In an ideal world the user could actually pattern match on the result of 
`entries[key]`. In this way they could match on it and perform special logic in 
both cases for really complex situations. This would make withDefault “just a 
convenience”, so we aren’t pressured to add more methods like it every time 
someone has a new Even More Complex use-case. e.g.:

switch map.entries[key] {
case .Found(entry):
  if entry.value == 10 { 
    print(“Found a value too many times! Moving key to fast-path auxiliary 
  } else {
    entry.value += 1
case .NotFound(entry):
  print(“Found a value for the first time! Registering a bunch of extra 

But again, this is all dependent on a much more powerful SIL/ARC, and we just 
don’t know what we’re going to get at this stage.
swift-evolution mailing list

Reply via email to