danielsdeleo / deep_merge

Recursive Merging for Ruby Hashes

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Inconsistent behaviour between bang and no-bang method

rbpltr opened this issue · comments

commented
hash1 = { a: 1, b: 2 }
=> {:a=>1, :b=>2}

hash2 = { a: 3, c: 4 }
=> {:a=>3, :c=>4}

hash1.deep_merge(hash2)
=> {:a=>1, :b=>2, :c=>4}

hash1.deep_merge!(hash2)
=> {:a=>3, :b=>2, :c=>4}

This difference in behaviour seems counterintuitive. Usually the bang method is the destructive equivalent of the non-bang method returning the same result.

I want the behaviour of deep_merge! above where :a's value is overwritten but I don't want to apply it destructively to the original hash1 object. Can this be done?

i faced with expected behavior

irb(main):013:0> hash1 = { a: 1, b: 2 }
irb(main):014:0> hash2 = { a: 3, c: 4 }
irb(main):015:0> puts hash1
{:a=>1, :b=>2}
=> nil
irb(main):016:0> puts hash2
{:a=>3, :c=>4}
=> nil
irb(main):017:0> hash1.deep_merge(hash2)
=> {:a=>3, :b=>2, :c=>4}
irb(main):018:0> hash1.deep_merge!(hash2)
=> {:a=>3, :b=>2, :c=>4}
irb(main):019:0> hash1 = { a: 1, b: 2 }
irb(main):020:0> hash2 = { a: 3, c: 4 }
irb(main):021:0> hash1.deep_merge!(hash2)
=> {:a=>3, :b=>2, :c=>4}
irb(main):022:0> puts hash1
{:a=>3, :b=>2, :c=>4}
=> nil
irb(main):023:0> hash1 = { a: 1, b: 2 }
irb(main):024:0> hash2 = { a: 3, c: 4 }
irb(main):025:0> hash1.deep_merge(hash2)
=> {:a=>3, :b=>2, :c=>4}
irb(main):026:0> puts hash1
{:a=>1, :b=>2}
=> nil
irb(main):027:0>

I'm still seeing my reported behaviour:

$ ruby -v
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23]

$ gem list
...
deep_merge (1.2.2)
...

$ irb
irb(main):001> require 'deep_merge'
=> true
irb(main):002> hash1 = { a: 1, b: 2 }
=> {:a=>1, :b=>2}
irb(main):003> hash2 = { a: 3, c: 4 }
=> {:a=>3, :c=>4}
irb(main):004> hash1.deep_merge(hash2)
=> {:a=>1, :b=>2, :c=>4}
irb(main):005> hash1.deep_merge!(hash2)
=> {:a=>3, :b=>2, :c=>4}

Edit: Actually, I think what I'm observing is #26. The non-bang method destructively modifies hash1:

$ irb
irb(main):001> require 'deep_merge'
=> true
irb(main):002> hash1 = { a: 1, b: 2 }
=> {:a=>1, :b=>2}
irb(main):003> hash2 = { a: 3, c: 4 }
=> {:a=>3, :c=>4}
irb(main):004> hash1.deep_merge(hash2)
=> {:a=>1, :b=>2, :c=>4}
irb(main):005> hash1
=> {:a=>1, :b=>2, :c=>4}

Edit 2: But that doesn't explain the inconsistent behaviour:

irb(main):006> hash1 = { a: 1, b: 2 }
=> {:a=>1, :b=>2}
irb(main):007> hash2 = { a: 3, c: 4 }
=> {:a=>3, :c=>4}
irb(main):008> hash1.deep_merge!(hash2)
=> {:a=>3, :b=>2, :c=>4}

it modifies by design, which is confusing ... fix to remove it #59