From: David MacMahon Date: 2013-08-18T00:55:23-07:00 Subject: [ruby-core:56717] Re: [ruby-trunk - Feature #7739] Define Hash#| as Hash#reverse_merge in Rails On Aug 17, 2013, at 5:44 PM, rosenfeld (Rodrigo Rosenfeld Rosas) wrote: > As I stated in #8772, I believe #| being implemented as #reverse_merge instead of #merge is confusing. I believe the original example in the description makes sense though. Why do you think that... {a:1, b:1} | {b:2, c:2) #=> {a:1, b:2, c:2} # merge-like ...is less confusing than... {a:1, b:1} | {b:2, c:2) #=> {a:1, b:1, c:2} # reverse_merge-like ...? For conflicting keys, the reverse_merge-like behavior gives precedence to the values of the left hand side, which I find reminiscent of the short-circuit behavior of || and &&. The merge-like behavior gives precedence to the values of the right hand side, which seems unusual IMHO. In addition to the short-circuit behavior of || and &&, Array#| also already gives precedence to the left hand side by preserving the order of the original array: [ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ] > Those alias would already be useful in cases people are using reverse_merge: > > options.reverse_merge! a: 1 > > options = {a: 1} | options # not exactly the same, but usually has the same effect on most well written code But wouldn't "options |= {a: 1}" be even more concise and similar in form to the "foo ||= 1" idiom? By having Hash#| be an alias for reverse_merge, this also wouldn't be exactly the same as reverse_merge!, but I suspect it would be effectively the same for a majority of uses. For "options" being passed in as a method parameter, I think it would be better than reverse_merge! because it doesn't modify/pollute the caller's Hash. There is a performance trade off (create new object and not pollute caller's Hash vs no new object but pollute caller's Hash) that needs to be considered, but for performance sensitive cases one could use reverse_merge! explicitly. > I'd even be fine with #>> as an alias for reverse_merge! > > options >>= {a: 1} # options.reverse_merge! a: 1 I'm not opposed to #>>= being reverse_merge!. I'm not thrilled with it either, but maybe it's just my C++ extraction operator days haunting me! :-) Dave