Feature #8499

Importing Hash#slice, Hash#slice!, Hash#except, and Hash#except! from ActiveSupport

Added by Kenta Murata over 1 year ago. Updated 8 months ago.

[ruby-core:55330]
Status:Assigned
Priority:Normal
Assignee:Yukihiro Matsumoto

Description

According to my experiences, the following two idioms often appeare in application codes.

  1. hash = other_hash.select { |k, | [:key1, :key2, :key3].include? k }
  2. hash = other_hash.reject { |k, | [:key1, :key2, :key3].include? k }

On Rails, they can be written in the following forms by using ActiveSupport's features.

  1. hash = other_hash.slice(:key1, :key2, :key3)
  2. hash = other_hash.except(:key1, :key2, :key3)

I think the latter forms are shorter and more readable than the former ones.

So I propose to import the following methods from ActiveSupport:

  • Hash#slice
  • Hash#slice!
  • Hash#except
  • Hash#except!

patch.diff Magnifier - built-in Hash#slice, Hash#slice!, Hash#except, and Hash#except! (4.05 KB) Masaki Matsushita, 07/26/2013 10:58 PM

patch2.diff Magnifier (4.07 KB) Masaki Matsushita, 07/29/2013 12:24 PM

History

#1 Updated by Shota Fukumori over 1 year ago

+1

#2 Updated by Zachary Scott over 1 year ago

Hello,

On Thu, Jun 6, 2013 at 4:12 PM, mrkn (Kenta Murata) muraken@gmail.com wrote:

On Rails, they can be written in the following forms by using ActiveSupport's features.

  1. hash = other_hash.slice(:key1, :key2, :key3)
  2. hash = other_hash.reject(:key1, :key2, :key3}

Do you mean "other_hash.except(...)"? There is already Hash#reject

#3 Updated by Nobuyoshi Nakada over 1 year ago

  • Description updated (diff)

#4 Updated by Kenta Murata over 1 year ago

zzak (Zachary Scott) wrote:

Hello,

On Thu, Jun 6, 2013 at 4:12 PM, mrkn (Kenta Murata) muraken@gmail.com wrote:

On Rails, they can be written in the following forms by using ActiveSupport's features.

  1. hash = other_hash.slice(:key1, :key2, :key3)
  2. hash = other_hash.reject(:key1, :key2, :key3}

Do you mean "other_hash.except(...)"? There is already Hash#reject

Yes, It's my mistake!

How can I edit the issue description?

#5 Updated by Kenta Murata over 1 year ago

  • Description updated (diff)

I could fix the description.

#6 Updated by Nobuyoshi Nakada over 1 year ago

Or enhance the existing methods?

#7 Updated by Kenta Murata over 1 year ago

nobu (Nobuyoshi Nakada) wrote:

Or enhance the existing methods?

I think Hash#[] with the multiple arguments can be an alternative of Hash#slice.

#8 Updated by Charlie Somerville over 1 year ago

+1

#9 Updated by Nobuyoshi Nakada over 1 year ago

mrkn (Kenta Murata) wrote:

I think Hash#[] with the multiple arguments can be an alternative of Hash#slice.

Hash#[] should return the values, not the pairs.

#11 Updated by Ilya Vorontsov over 1 year ago

mrkn (Kenta Murata) wrote:

nobu (Nobuyoshi Nakada) wrote:

Or enhance the existing methods?

I think Hash#[] with the multiple arguments can be an alternative of Hash#slice.

There was a proposal (can't find it) to make indexing by multiple arguments to work as nested hashes so that hsh[:a,:b,:c] works as (hsh[:a] && hsh[:a][:b] && hsh[:a][:b][:c]). Your proposal automatically blocks this proposal.

#12 Updated by Kenta Murata over 1 year ago

prijutme4ty (Ilya Vorontsov) wrote:

mrkn (Kenta Murata) wrote:

nobu (Nobuyoshi Nakada) wrote:

Or enhance the existing methods?

I think Hash#[] with the multiple arguments can be an alternative of Hash#slice.

There was a proposal (can't find it) to make indexing by multiple arguments to work as nested hashes so that hsh[:a,:b,:c] works as (hsh[:a] && hsh[:a][:b] && hsh[:a][:b][:c]). Your proposal automatically blocks this proposal.

My proposal primaliry consists of Hash#slice, Hash#except, and bang versions of them.
Hash#[] is optional.

#13 Updated by Clay Trump over 1 year ago

Yay, +1 for slice & except

BTW, makes no sense to me if h[:foo, :bar] returns keys and values in a
hash while h[:foo] returns a value.


<lay trum/>

#14 Updated by Vipul Amler over 1 year ago

+1

#15 Updated by Kenta Murata over 1 year ago

On Fri, Jun 7, 2013 at 1:50 AM, Zachary Scott zachary@zacharyscott.net wrote:

Please update description if the proposal has changed (ie: Hash#[])

I mentioned Hash#[] as the reply to nobu's comment #6.
It has not changed my proposal.
My proposal only consists of slice, slice!, except, and except!.

--
Kenta Murata
OpenPGP FP = 1D69 ADDE 081C 9CC2 2E54 98C1 CEFE 8AFB 6081 B062

#16 Updated by Nobuyoshi Nakada over 1 year ago

I meant Hash#select and Hash#reject by "the existing methods".

i.e.:

hash = other_hash.select(:key1, :key2, :key3)
hash = other_hash.reject(:key1, :key2, :key3)

But Hash#slice and Hash#except seems fine.

#17 Updated by Masaki Matsushita over 1 year ago

How about this implementation?

#18 Updated by Yukihiro Matsumoto over 1 year ago

The slice method (Array#slice) retrieve "a slice of elements" from an Array.
Considering that, slice is not a good name for the behavior.

So, I prefer Nobu's idea in comment #16

hash = other_hash.select(:key1, :key2, :key3)
hash = other_hash.reject(:key1, :key2, :key3)

Matz

#19 Updated by Kazuhiro NISHIYAMA over 1 year ago

In attached patch.diff

assert_equal({1=>2, 3=>4}, h.slice!(1, 3))

but ActiveSupport's h.slice!(1, 3) returns {5=>6}.

http://api.rubyonrails.org/classes/Hash.html#method-i-slice-21

#20 Updated by Nobuyoshi Nakada over 1 year ago

I've missed the returned values until I've implemented it actually.

  • In ActiveSupport

    • Hash#slice! keeps the given keys and returns removed key/value pairs.
    • Hash#except! removes the given keys and returns self.
  • In this proposal

    • Hash#slice! removes the given keys and returns removed key/value pairs.
    • Hash#except! is same as ActiveSupport.
  • Existing methods

    • Hash#select! keeps the given (by the block) keys and returns self or nil.
    • Hash#reject! removes the given (by the block) keys and returns self or nil.

I don't think changing the result semantics by if any arguments are given is good idea.
What I've thoutht about Hash#slice! was Hash#extract! in ActiveSupport actually.
So what about Hash#extract, Hash#except and those !-versions?

#21 Updated by Kenta Murata over 1 year ago

The attached file is not a part of my proposal. It made by Glass_saga. My proposal is the same as ActiveSupport.

#22 Updated by Masaki Matsushita over 1 year ago

I'm sorry for my wrong implementation.
patch2.diff makes Hash#slice! and #except! behave the same as ActiveSupport.
However, I think it isn't good idea to import Hash#slice! and #except! from ActiveSupport as it is.

Because:

  • They returns self if no changes were made. It is inconsistent with other built-in methods like #select! and #reject!.
  • #slice! returns rest of hash, not slice of hash like following. It may be confusing.
hash = {1=>2,3=>4,5=>6}
hash.slice!(1,3) #=> {5,6}
hash #=> {1=>2,3=>4}

#23 Updated by Hiroshi SHIBATA about 1 year ago

  • Target version changed from 2.1.0 to current: 2.2.0

#24 Updated by Nobuyoshi Nakada 8 months ago

  • Description updated (diff)

Another name, Hash#only.
http://blog.s21g.com/articles/228

Also available in: Atom PDF