Issue #20300 has been updated by rubyFeedback (robert heiler).
Not so sure about these names. Note that get_and_set() may have people wonder why it is
not set_and_get(). :D
In regards to .update_value() people could ask why the old value is returned rather than
the
new one.
I guess exchange_value is a bit more specific than the other variants, as people can say
"I put in value x, as the new value, and get, in exchange, value y which was the old
one".
I don't have a better name suggestion though, but just from the alternatives so far I
think nobu's suggestion is at the least better than the other ones, in my opinion.
I don't have any particular opinion on the suggested functionality; in my own code I
kind of keep setters and getters usually separate, or, e. g. first set and then get (or
get first, assign to a variable, then set to a new value). It would be nice if we could
have some kind of "universal idiom" for the desired functionality though - could
make it easier if different programming languages, at the least OOP-centric ones, would
use the same name/terminology for that. That would make naming things easier too, or at
the least more consistent across programming languages, just like setters and getters are
fairly well-established idioms in OOP-centric languages (ruby is kind of multi-paradigm; I
don't know how functional programming languages solve this issue of setting and
obtaining a new or old value in one go, so I can't comment on that).
----------------------------------------
Feature #20300: Hash: set value and get pre-existing value in one call
https://bugs.ruby-lang.org/issues/20300#change-106988
* Author: AMomchilov (Alexander Momchilov)
* Status: Open
----------------------------------------
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:
```ruby
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#update_value`, which has semantics are similar to this Ruby
snippet:
```ruby
class Hash
# Exact method name TBD.
def update_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 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
```ruby
h = { k: "old value" }
# Does only a single hash look-up
old_value = h.update_value(:k, "new value")
use(old_value)
```
--
https://bugs.ruby-lang.org/