Skip to content

Entry API equivalent for Sets #1490

Closed
@Gankra

Description

@Gankra

By merging RFC 1194, set recovery we have acknowledged that the values of keys "matter". That is, it's reasonable to have an equal key, but want to know about the details of the stored key.

That RFC added fn get(&T) -> Option<&T>, take(&T) -> Option<T>, and replace(T) -> Option<T>.

However, what if I have an entry-like situation?

Today, this is the best we can do:

fn get_or_insert(set: &mut HashSet<Key>, key: Key) -> &Key {
  let dupe = key.clone();
  if !set.contains(&key) {
    set.insert(key)
  }
  set.get(&dupe).unwrap();
}

Not only do we incur double-lookup (triple-lookup in the insertion case!), we also incur an unconditional Clone even though we already had a by-value key!

Optimally, we could write

fn get_or_insert(set: &mut HashSet<Key>, key: Key) -> &Key {
  set.entry(key).into_ref()
}

What's the entry API for sets? Well, a heck of a lot simpler. The entry API on maps is all about deferred value handling, and that doesn't make sense for sets.

  • Vacant::insert and Occupied::insert don't make sense because we already have the key
  • Occupied::get_mut and into_mut don't make sense because we don't acknowledge key mutation
  • Occupied::get and into_ref (to mirror into_mut), and remove are the only ones that make sense
  • It may also make sense to provide something like replace() to explicitly overwrite the old key... or something..?

So basically it would be something like entry(K) -> WasVacant(Entry) | WasOccupied(Entry). Critically, you get the same interface no matter what state the world was in, because there's nothing to do in the Vacant case but insert what was already given.

Supporting this would probably mean expanding the Entry API to "care about keys".

I haven't thought about the full implications here, and I don't have the bandwidth to write a full RFC at the moment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-libs-apiRelevant to the library API team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions