【发布时间】:2015-03-27 22:24:37
【问题描述】:
Refinements 是 v2.0 的实验性补充,然后在 v2.1 中进行了修改并永久化。它通过提供“一种在本地扩展类的方法”来避免“猴子补丁”。
我尝试将Refinements 应用于this recent question,我将对此进行简化:
a = [[1, "a"],
[2, "b"],
[3, "c"],
[4, "d"]]
b = [[1, "AA"],
[2, "B"],
[3, "C"],
[5, "D"]]
如果:
a[i].first == b[i].first
和
a[i].last.downcase == b[i].last.downcase
也就是说,字符串的匹配与大小写无关。
问题是确定a的元素个数匹配b的对应元素。我们看到答案是两个,偏移量为1 和2 的元素。
做到这一点的一种方法是猴子补丁String#==:
class String
alias :dbl_eql :==
def ==(other)
downcase.dbl_eql(other.downcase)
end
end
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 2
或者改用Refinements:
module M
refine String do
alias :dbl_eql :==
def ==(other)
downcase.dbl_eql(other.downcase)
end
end
end
'a' == 'A'
#=> false (as expected)
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 0 (as expected)
using M
'a' == 'A'
#=> true
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 2
但是,我想像这样使用Refinements:
using M
a.zip(b).count { |ae,be| ae == be }
#=> 0
但是,如您所见,这给出了错误的答案。那是因为我正在调用Array#==,而细化不适用于Array。
我可以这样做:
module N
refine Array do
def ==(other)
zip(other).all? do |ae,be|
case ae
when String
ae.downcase==be.downcase
else
ae==be
end
end
end
end
end
using N
a.zip(b).count { |ae,be| ae == be }
#=> 2
但这不是我想要的。我想做这样的事情:
module N
refine Array do
using M
end
end
using N
a.zip(b).count { |ae,be| ae == be }
#=> 0
但显然这不起作用。
我的问题:有没有办法优化String 以用于Array,然后优化Array 以用于我的方法?
【问题讨论】:
标签: ruby refinements