From: "chrisseaton (Chris Seaton)" Date: 2022-07-13T16:00:03+00:00 Subject: [ruby-core:109197] [Ruby master Feature#14564] `dig` opposite method Issue #14564 has been updated by chrisseaton (Chris Seaton). Instead of different `dig` and `bury` tools, a 'lens' abstraction could combine the two. ```ruby deep_hash = {a: {b: {c: {d: 100}}}} p deep_hash.dig(:a, :b, :c, :d) class Lens def self.lens(*keys) lens = Leaf.new(keys.pop) lens = Node.new(keys.pop, lens) until keys.empty? lens end class Node def initialize(key, child) @key = key @child = child end def get(object) @child.get object[@key] end def set(object, value) @child.set object[@key], value end end class Leaf def initialize(key) @key = key end def get(object) object[@key] end def set(object, value) object[@key] = value end end end lens = Lens.lens(:a, :b, :c, :d) p lens.get(deep_hash) lens.set deep_hash, 14 p lens.get(deep_hash) ``` ---------------------------------------- Feature #14564: `dig` opposite method https://bugs.ruby-lang.org/issues/14564#change-98336 * Author: nilcolor (Aleksey Blinov) * Status: Open * Priority: Normal ---------------------------------------- We have nice `dig` method that helps a lot. Though we didn't have an opposite method that allows setting a value. I know we already have these: https://bugs.ruby-lang.org/issues/11747 https://bugs.ruby-lang.org/issues/13179 Both were closed because of name or lack of use cases. Let me promote the new name for this: ~~~ ruby class Hash def expand(*where, value) where[0..-2].reduce(self) { |h, key| h[key] = h[key] || {} }[where[-1]] = value self end end {}.expand(:a, :b, :c, 42) # => {:a=>{:b=>{:c=>42}}} {}.expand(:a, 0, :c, 42) # => {:a=>{0=>{:c=>42}}} {a: {}}.expand(:a, :b, :c, 42) # => {:a=>{:b=>{:c=>42}}} {a: {b: nil}}.expand(:a, :b, :c, 42) # => {:a=>{:b=>{:c=>42}}} {a: {foo: "bar"}}.expand(:a, :b, :c, 42) # => {:a=>{:foo=>"bar", :b=>{:c=>42}}} {a: {b: "wat"}}.expand(:a, :b, :c, 42) # => TypeError: no implicit conversion of Symbol into Integer class Array def expand(*where, value) where[0..-2].reduce(self) { |a, idx| a[idx] = a[idx] || [] }[where[-1]] = value self end end [].expand(2, 1, 3, "?") # => [nil, nil, [nil, [nil, nil, nil, "?"]]] [1, [0, 2], []].expand(1, 1, "BAM") # => [1, [0, "BAM"], []] [1, [0, 2], []].expand(2, 0, "BAM") # => [1, [0, 2], ["BAM"]] ~~~ Use cases: working with deeply nested structures, used as parameters (`params[:a][:nested][:some_id] = 42`). In general, I think it's mostly useful for Hashes. Though having this on Array may be useful as well. -- https://bugs.ruby-lang.org/ Unsubscribe: