Feature #15863
closedAdd `Hash#slice!` and `ENV.slice!`
Description
Add Hash#slice!
In https://bugs.ruby-lang.org/issues/8499 we added Hash#slice
.
Hash#slice!
removes and returns the key/value pairs matching the given keys:
h = {a: 100, b: 200, c: 300}
h.slice!(:a) # => {:a=>100}
h # => {:b=>200, :c=>300}
h.slice!(:b, :c, :d) # => {:b=>200, :c=>300}
h # => {}
Note that, this method reflects the behavior of Active Support's
Hash#extract!
method that was added in 2009, see
https://github.com/rails/rails/commit/8dcf91ca113579646e95b0fd7a864dfb6512a53b
h = {a: 100, b: 200, c: 300}
h.extract!(:a) # => {:a=>100}
h # => {:b=>200, :c=>300}
h.extract!(:b, :c, :d) # => {:b=>200, :c=>300}
h # => {}
(There is a proposal to add Hash#extract
to Ruby - https://bugs.ruby-lang.org/issues/15831, but it has another method signature)
Active Support also has Hash#slice!
, see https://api.rubyonrails.org/v5.2/classes/Hash.html#method-i-slice-21.
It is quite different what this patch proposes, see how it works:
h = {a: 100, b: 200, c: 300}
h.slice!(:a) # => {:b=>200, :c=>300} # AS Hash#slice!
h # => {:a=>100}
h.slice!(:b, :c, :d) # => {:a=>100} # AS Hash#slice!
h # => {}
I think Hash#slice!
in Ruby should work in the same way as Hash#extract!
from Active Support,
there is one argument:
-
https://bugs.ruby-lang.org/issues/8499#note-31
It should behave in the wayHash#slice
does, except one thing
Hash#slice!
modifies the object. (See, for instance, howArray#slice
and
Array#slice!
work, they return the same value)
But I would like to discuss it more to choose the right behavior for the
proposed method. (Maybe there are good arguments why we should add Hash#slice!
with behavior as it is in Active Support)
Add ENV.slice!
The method removes and returns the key/value pairs matching the given keys.
ENV.slice!("PORT", "RAILS_ENV") # => {"PORT"=>"3000", "RAILS_ENV"=>"development"}
Pull Request: https://github.com/ruby/ruby/pull/2195
Patch: https://patch-diff.githubusercontent.com/raw/ruby/ruby/pull/2195.patch
Updated by bogdanvlviv (Bogdan Denkovych) over 5 years ago
- Tracker changed from Bug to Feature
- Backport deleted (
2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: UNKNOWN)
Updated by shevegen (Robert A. Heiler) over 5 years ago
I do not know how Hash#extract from Active* works but the name does not make to me
a whole lot of sense to me; however had, we have Hash#slice already so I guess it may
make sense to add .slice!; and if so, it may make sense to add it for ENV as
ENV is very hash-like. But I may miss something altogether - this may be best
to actually suggest to the upcoming developer meeting, since it is a fairly small
request/possible change, anyway. (I don't feel I should add it myself because
you suggested it so you should be in control over as to whether you want to
suggest it or not - that is not my decision what you make of course. :))
The next meeting is at:
https://bugs.ruby-lang.org/issues/15782
As for behaviour - this is not necessarily specific to your proposal alone,
but I think ruby users will expect that the trailing "!" indicates a warning
or rather an operation that may be "dangerous" or have side effects - the most
usual one being modifying the receiver in place (or something like that). Not
all methods have a trailing !, for example, replace() on class String. I think
the bottom line is that matz wanted a simple visual cue/indicator for ruby.
So I think whatever the feature request or desired change, I think the most
natural assumption would be that a variant with ! will do precisely the same
as the non-! variant, as action, but without modifying the object at hand.
It is for this reason that I believe that .slice! could (or should) not model
any other behaviour than what .slice() is doing right now. But as said, I may
be missing something; perhaps there was a reason .slice!() was not added,
I would not know.
Updated by nobu (Nobuyoshi Nakada) over 5 years ago
- Related to Feature #8499: Importing Hash#slice, Hash#slice!, Hash#except, and Hash#except! from ActiveSupport added
Updated by mame (Yusuke Endoh) over 5 years ago
It should behave in the way Hash#slice does, except one thing Hash#slice! modifies the object. (See, for instance, how Array#slice and Array#slice! work, they return the same value)
I agree that it is ideal. However, in practical, it would be difficult to add to Ruby a feature whose behavior is completely different from the existing feature in Rails.
If you really want to do this, you need first to persuade the developers of ActiveSupport to deprecate (and then remove) the current Hash#slice!
, wait for a few years, and finally we can add it to Ruby with a "correct" behavior.
Updated by matz (Yukihiro Matsumoto) over 5 years ago
- Status changed from Open to Rejected
I don't think we have seen the use-case that this method is absolutely necessary.
Let me see the real-world use-case, please.
Matz.
Updated by bogdanvlviv (Bogdan Denkovych) over 5 years ago
Let me see the real-world use-case, please.
Since proposed Hash#slice!
method is the same as Hash#extract!
from the Active Support, there is one use-case where we have some options
then we extract some known by keys options and assign it to path_options
variable to be able to use them later in one way and the rest options
to use in another way:
https://github.com/rails/rails/blob/c1e949e9e618f75dc446ffa584c3b441c48714b1/actionview/lib/action_view/helpers/asset_tag_helper.rb#L89