为啥 to_proc 在 Ruby 改进中不起作用?

Posted

技术标签:

【中文标题】为啥 to_proc 在 Ruby 改进中不起作用?【英文标题】:Why doesn't to_proc work inside Ruby refinements?为什么 to_proc 在 Ruby 改进中不起作用? 【发布时间】:2016-05-21 20:50:40 【问题描述】:

似乎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)

这是预期的行为吗?有解决办法吗?

【问题讨论】:

情况正好相反。细化中定义的方法在 Symbol#to_proc 创建的过程中不起作用。 【参考方案1】:

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 类(!) 的上下文中。如文档中所述:

当控制转移到范围之外时,细化被停用。

这里的类比是私有方法。虽然,虽然它完全按照文档中的说明,但我不确定这种行为是否是有意的。我认为,口译员应该注意这种情况。但是这个问题最好解决 Matz :)

附注问得好!

【讨论】:

【参考方案2】:

当然是有意的。细化的范围是模块块或调用using 的文件。在您的(&:sum) 中,您没有(明确地)调用方法sum;你那里只有一个符号:sum。当使用Symbol#to_proc 时,调用是在Ruby C 实现中的某处完成的。这种环境是您的改进无效的地方。

一种解决方法是显式调用该文件中的方法。

【讨论】:

以上是关于为啥 to_proc 在 Ruby 改进中不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

:footnotes 扩展在 Redcarpet Ruby gem 中不起作用

字符串形式的正则表达式在 Ruby 中不起作用

ruby to_proc.rb

为啥 setVisibility() 在 onResumeFragments() 中不起作用?

为啥 IOCP 在 BeginExecuteReader 中不起作用

为啥 heightForHeaderInSection 在 iOS 4.3 中不起作用?