Project

General

Profile

Actions

Feature #20769

closed

Add `Hash#transform_value`

Added by seanpdoyle (Sean Doyle) 3 months ago. Updated 3 months ago.

Status:
Feedback
Assignee:
-
Target version:
-
[ruby-core:119332]

Description

Add Hash#transform_value as a specialized, key-specific version of Hash#transform_values.

hash = { image: "https://example.com/image.jpg" }
mutated_hash = hash.transform_value(:image) { |url| download(url) }

hash # => { image: "https://example.com/image.jpg" }
mutated_hash # => { image: File<...> }

hash.transform_value!(:image) { |url| download(url) }
hash # => { image: File<...> }

Similar value transformation can be achieved through variable assignment and direct mutation:

hash = { image: "https://example.com/image.jpg" }

hash.merge(image: download(hash[:image]))

hash[:image] = download(hash[:image])

While simple and currently supported, it requires a local variable (and therefore poses some challenges when chaining other methods) and repeats the Hash key in both the reading and writing portions of the code.

Updated by nobu (Nobuyoshi Nakada) 3 months ago

hash.merge(image: nil) {|_, url| download(url)}

hash.merge!(image: nil) {|_, url| download(url)}

Updated by seanpdoyle (Sean Doyle) 3 months ago

Thank you for sharing that code sample. It demonstrates an interesting way to use Hash#merge with a block argument.

When the key argument is absent from the Hash, a call to Hash#transform_value would be a no-operation. I apologize for not including this in the original example:

hash  = { foo: "value" }
transformed_hash = hash.transform_key(:bar) { |value| fail "This block is never yielded" }
transformed_hash # => { foo: "value" }

nobu (Nobuyoshi Nakada) wrote in #note-1:

hash.merge(image: nil) {|_, url| download(url)}

hash.merge!(image: nil) {|_, url| download(url)}

Using Hash#merge in the way you have shared does reduce the number times the key name is repeated.

However, without a guarding conditional call to hash.key?(:image), the returned Hash would include image: nil when an :image key was not initially present:

hash = {}
transformed_hash = hash.merge(image: nil) { |_, url| download(url) }
transformed_hash # => { image: nil }

hash = {}
transformed_hash = hash.merge(image: nil) { |_, url| download(url) } if hash.key?(:image)
transformed_hash # => {}

Updated by matz (Yukihiro Matsumoto) 3 months ago

  • Status changed from Open to Feedback

I don't see the real-world use-case for the proposed method.

Matz.

Actions

Also available in: Atom PDF

Like1
Like0Like1Like0