Range#include 的最小接口?支持

Minimal interface for Range#include? support

我想让我的无年约会 class 与 Range#include?according to the docs 相处得很好,它所要实现的只是 <=>:

class Count
  include Comparable

  attr_reader :value

  def initialize(value)
    @value = value
  end

  def <=>(other)
    value <=> other.value
  end
end

让我们试试 Ruby 3.1.1:

(Count.new(1)..Count.new(5)).include? Count.new(3)
# => in `each': can't iterate from Count (TypeError)

我不明白为什么要在此处进行迭代,each 应该不是计算包含的必要条件。

知道我在这里做错了什么吗?感谢您的提示!

文档不正确或(我怀疑)已过时。 Range#cover? 以您期望的方式工作 [粗体 强调我的]:

cover?(object)true or false

Returns true if the given argument is within self, false otherwise.

With non-range argument object, evaluates with <= and <.

Range#include? 的文档包含一个有点不祥的声明 [粗体 强调我的]:

If begin and end are numeric, include? behaves like cover?

[…]

But when not numeric, the two methods may differ:

('a'..'d').include?('cc') # => false
('a'..'d').cover?('cc')   # => true

在这里您可以看到不同之处:Range#cover? 计算结果为 true 因为 'a' <= 'cc' && 'cc' <= 'd',而 Range#include? 计算结果为 false 因为 ('a'..'d').to_a == ['a', 'b', 'c', 'd']因此 ('a'..'d').each.include?('cc') 是假的。

请注意,介绍性示例使用 Time still works because Time is explicitly special-cased in the spec

a spec which says both Range#include? and Range#cover? use <=>, but it is only tested with Integer,我们从上面的不祥文档中知道 Range#include?Range#cover? 表现相同。

有相当多的 special-casing 持续 Range 秒,这不是第一次导致错误 and/or non-intuitive 行为:

就个人而言,我不是这一切的忠实粉丝special-casing。我假设这样做是出于性能原因,但获得更好性能的方法不是在语言规范中添加奇怪的特殊情况,而是 删除 它们使语言更简单,从而更容易优化。或者,换句话说:在任何给定的时间点,编译器编写者要么花时间实现奇怪的特殊情况,要么花时间进行出色的优化,但不能两者兼而有之。 XRuby, Ruby.NET, MacRuby, MagLev, JRuby, IronRuby, TruffleRuby, Rubinius, Topaz, 朋友们有表明获取方式 high-performance Ruby 是强大的编译器,不奇怪 hand-rolled special-cased C代码。

我会file a bug,如果只是为了对文档和规范进行一些澄清的话。