为什么 to_proc 在 Ruby 优化中不起作用?
Why doesn't to_proc work inside Ruby refinements?
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)
这是预期的行为吗?有解决方法吗?
NB 下面的答案对于遗留红宝石是正确的。在 Ruby 2.5+ map(&:sum)
中工作 如预期的那样 .
Scoping of refinements 仅限于 当前上下文 。由于优化旨在不是全局,与猴子补丁相反,任何从外部调用优化方法的尝试都会被阻止。在下面的代码中:
puts [[1, 2, 3]].map { |array| array.sum } # => 6
范围很好,我们在定义此优化的同一范围内。但是在这里:
puts [[1, 2, 3]].map(&:sum)
范围转移到 Symbol
class 的上下文 (!)。如文档中所述:
When control is transferred outside the scope the refinement is deactivated.
这里类比私有方法。虽然,虽然它与文档中所述完全相同,但我不确定这种行为是否有意为之。我认为,口译员应该注意这种情况。但是这个问题最好解决 Matz :)
P.S.好问题!
当然是故意的。细化的范围是模块块或调用 using
的文件。在您的 (&:sum)
中,您没有(明确地)调用方法 sum
;你那里只有一个符号 :sum
。当使用 Symbol#to_proc
时,调用是在 Ruby C 实现中的某处完成的。那个环境就是你的细化没有效果的地方。
解决方法是在该文件中显式调用该方法。
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)
这是预期的行为吗?有解决方法吗?
NB 下面的答案对于遗留红宝石是正确的。在 Ruby 2.5+ map(&:sum)
中工作 如预期的那样 .
Scoping of refinements 仅限于 当前上下文 。由于优化旨在不是全局,与猴子补丁相反,任何从外部调用优化方法的尝试都会被阻止。在下面的代码中:
puts [[1, 2, 3]].map { |array| array.sum } # => 6
范围很好,我们在定义此优化的同一范围内。但是在这里:
puts [[1, 2, 3]].map(&:sum)
范围转移到 Symbol
class 的上下文 (!)。如文档中所述:
When control is transferred outside the scope the refinement is deactivated.
这里类比私有方法。虽然,虽然它与文档中所述完全相同,但我不确定这种行为是否有意为之。我认为,口译员应该注意这种情况。但是这个问题最好解决 Matz :)
P.S.好问题!
当然是故意的。细化的范围是模块块或调用 using
的文件。在您的 (&:sum)
中,您没有(明确地)调用方法 sum
;你那里只有一个符号 :sum
。当使用 Symbol#to_proc
时,调用是在 Ruby C 实现中的某处完成的。那个环境就是你的细化没有效果的地方。
解决方法是在该文件中显式调用该方法。