From: ko1@... Date: 2015-05-28T09:57:47+00:00 Subject: [ruby-core:69392] [Ruby trunk - Bug #11182] Refinement with alias causes strange behavior Issue #11182 has been updated by Koichi Sasada. Let's discuss with use cases. I don't have good example, but please assume we want to make new Hash class to support something like HashWithIndifferentAccess. Okay, we need an extra Hash class doing something special. ```ruby class MyHash < Hash def initialize *args args.each{|(k, v)|self[k] = v} end alias iterate each end h = MyHash.new([:b, 1], [:a, 2]) h.each{|k, v| p [k, v]} # [:b, 1] [:a, 2] ``` Good. Next time, I invented a nice refinement to iterate Hash contents by ordered. ```ruby module OrderedHashEach refine Hash do def each sort.each{|k, v| yield k, v } end end end using OrderedHashEach {b: 1, a: 2}.each{|k, v| p [k, v]} # [:a, 2], [:b, 1] ``` Excellent. And of course, we can combine MyHash and OrderedHashEach. ```ruby module OrderedHashEach refine Hash do def each sort.each{|k, v| yield k, v } end end end class MyHash < Hash def initialize *args args.each{|(k, v)|self[k] = v} end end h = MyHash.new([:b, 1], [:a, 2]) using OrderedHashEach h.each{|k, v| p [k, v]} # [:a, 2] [:b, 1] ``` Great. Wait. `each` is not good terminology for our project. Use `iterate` intead. ```ruby module OrderedHashEach refine Hash do def each sort.each{|k, v| yield k, v } end end end class MyHash < Hash def initialize *args args.each{|(k, v)|self[k] = v} end alias iterate each end h = MyHash.new([:b, 1], [:a, 2]) using OrderedHashEach h.iterate{|k, v| p [k, v]} # [:b, 1] [:a, 2] ``` It doesn't affect :( It is unexpected result for me. Note that I don't want to change this specification. I want to know what is ideal specification. This time, I made a scenario that we may want to use M::C#foo. ---------------------------------------- Bug #11182: Refinement with alias causes strange behavior https://bugs.ruby-lang.org/issues/11182#change-52668 * Author: Koichi Sasada * Status: Feedback * Priority: Normal * Assignee: Koichi Sasada * ruby -v: 2.3dev * Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN ---------------------------------------- The following script causes strange behavior. ```ruby class C def foo p "C" end end module M refine C do def foo p "Refiend C" end end end class D < C alias bar foo end using M D.new.bar #=> t.rb:21:in `
': undefined method `bar' for # (NoMethodError) ``` It seems strange. Maybe (1) C#foo or (2) M#C#foo should be called. But I'm not sure which is suitable. Previous versions: ``` ruby 2.0.0p606 (2014-11-28 revision 48636) [i386-mswin32_110] t.rb:9: warning: Refinements are experimental, and the behavior may change in future versions of Ruby! "C" ruby 2.1.5p312 (2015-03-10 revision 49912) [i386-mswin32_110] "C" ``` ---Files-------------------------------- 1.PNG (38.7 KB) 2.PNG (43.7 KB) 4.PNG (38.5 KB) 3.PNG (37.9 KB) alias_affected_by_original_refinement.diff (1.34 KB) 6.PNG (36.6 KB) 7.PNG (40.7 KB) -- https://bugs.ruby-lang.org/