似乎to_proc
不适用于细化中定义的方法:
module ArrayExtensions
refine Array do
def sum
reduce(0, :+)
end
end
end
using ArrayExtensions
puts [[1, 2, 3]].map { |array| array.sum } # => 6
puts [[1, 2, 3]].map(&:sum) # => array.rb:13:in `map': undefined method `sum' for [1, 2, 3]:Array (NoMethodError)
puts [1, 2, 3].method(:sum).to_proc.call # => array.rb:14:in `method': undefined method `sum' for class `Array' (NameError)
这是预期的行为吗?有解决方法吗?
注意 以下答案对于传统红宝石是正确的。在 Ruby 2.5+ 中,map(&:sum)
按预期工作。
细化的范围仅限于当前上下文。由于细化不是全局的,与猴子补丁相反,因此阻止了从外部调用精炼方法的任何尝试。在下面的代码中:
puts [[1, 2, 3]].map { |array| array.sum } # => 6
范围很好,我们在定义此细化的同一范围内。但在这里:
puts [[1, 2, 3]].map(&:sum)
作用域将转移到类 (!( Symbol
上下文中。如文档中所述:
当控制权转移到范围之外时,优化将被停用。
这里的类比将是一种私人方法。虽然它与文档中所述完全相同,但我不确定这种行为是否是有意的。我认为,口译员应该注意这种情况。但这个问题最好解决马茨:)
附言问得好!
当然是有意的。优化的范围是模块块或调用using
的文件。在你的(&:sum)
中,你没有(显式地(调用方法sum
;你那里只有一个符号:sum
。当使用Symbol#to_proc
时,调用是在 Ruby C 实现中的某个地方完成的。这种环境是你的细化无效的地方。
解决方法是显式调用该文件中的方法。