Project

General

Profile

Actions

Feature #20300

open

Hash: set value and get pre-existing value in one call

Added by AMomchilov (Alexander Momchilov) 9 months ago. Updated 6 months ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:116940]

Description

When using a Hash, sometimes you want to set a new value, and see what was already there. Today, you have to do this in two steps:

h = { k: "old value" }

# 1. Do a look-up for `:k`.
old_value = h[:k]
# 2. Do another look-up for `:k`, even though we just did that!
h[:k] = "new value"

use(old_value)

This requires two separate Hash look-ups for :k. This is fine for symbols, but is expensive if computing #hash or #eql? is expensive for the key. It's impossible to work around this today from pure Ruby code.

One example use case is Set#add?. See https://bugs.ruby-lang.org/issues/20301 for more details.

I propose adding Hash#exchange_value, which has semantics are similar to this Ruby snippet:

class Hash
  # Exact method name TBD.
  def exchange_value(key, new_value)
    old_value = self[key]
    self[key] = new_value
    old_value
  end
end

... except it'll be implemented in C, with modifications to tbl_update that achieves this with a hash-lookup.

I'm opening to alternative name suggestions. @nobu (Nobuyoshi Nakada) came up with exchange_value, which I think is great.

Here's a PR with a PoC implementation: https://github.com/ruby/ruby/pull/10092

h = { k: "old value" }

# Does only a single hash look-up
old_value = h.exchange_value(:k, "new value")

use(old_value)

Related issues 2 (1 open1 closed)

Related to Ruby master - Bug #20301: `Set#add?` does two hash look-upsOpenActions
Related to Ruby master - Feature #17342: Hash#fetch_setFeedbackActions
Actions

Also available in: Atom PDF

Like5
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like1Like1Like1Like0Like0Like0Like1Like1Like0Like0Like0Like0Like0