Range#include 的最小接口?支持

发布于 2025-01-18 08:04:29 字数 749 浏览 3 评论 0 原文

我想让我的一年的日期班级播放 range#include?根据文档,它必须实现的只是< =>

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)

我不明白为什么它在此处尝试迭代,每个不需要弄清楚包含。

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

I'd like to make my yearless dates class play nice with Range#include?, according to the docs, all it has to implement is <=>:

class Count
  include Comparable

  attr_reader :value

  def initialize(value)
    @value = value
  end

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

Let's try on Ruby 3.1.1:

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

I don't get why it's trying to iterate here, each should not be necessary to figure out inclusion.

Any idea what am I doing wrong here? Thanks for your hints!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一口甜 2025-01-25 08:04:29

该文档不正确或(我怀疑)过时。 范围#cover#cover# 按照您期望的方式[ Bold 强调我]:

cover?(object) true false

返回 true 如果给定参数在 self , false 否则。

使用非范围参数对象,用 &lt; = &lt; 。 >

range#rangage#包括吗? 包含一个不祥的陈述[粗体重点]

如果开始和结束是数字, 的行为 cover?

[…]

但是当不是数字时,这两种方法可能会有所不同:

 ('a'..'d')。inclage?('cc')#=&gt;错误的
('a'..'d')。封面?('cc')#=&gt;真的
 

在这里您可以看到差异:范围#cover?评估 true ,因为'a'&lt; ='cc'&amp;&amp; 'cc'&lt; ='d',而范围#include?评估 false 是因为('a'a'..'d') 。 是假的。

请注意,使用在规格中明确特殊。

那里 is 一个说明范围#include?范围#cover?使用&lt; =&gt; 的规格仅使用 integer S上面的不祥文档<代码>范围#包括?范围#封面?行为相同。

对于 range> s,有很多特殊casing正在进行中,这不是第一次导致错误和/或非直觉行为:

我个人不是这是所有这些特殊观念的忠实拥护者。我认为这样做是出于绩效原因,但是获得更好的性能的方法不是在语言规范中添加怪异的特殊情况,而是删除它们,这使语言变得更简单,因此更容易优化。 。或者,换句话说:在任何给定的时间点,编译器作者可以花费时间来实施奇怪的特殊情况或出色的优化,但不会两者兼而有之。 Xruby,Ruby.net,Macruby,Maglev,Jruby,Ironruby,Truffleruby,Rubinius,Topaz和Friends表明,获得高性能Ruby的方法是强大的编译器,不是怪异的手工滚动的专用C代码。

我会文件bug 文档和规格。

The documentation is incorrect or (rather, I suspect) outdated. Range#cover? works the way you expect [bold emphasis mine]:

cover?(object)true or false

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

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

The documentation for Range#include? contains a somewhat ominous statement [bold emphasis mine]:

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

Here you can see the difference: Range#cover? evaluates to true because 'a' <= 'cc' && 'cc' <= 'd', whereas Range#include? evaluates to false because ('a'..'d').to_a == ['a', 'b', 'c', 'd'] and thus ('a'..'d').each.include?('cc') is falsey.

Note that the introductory example using Time still works because Time is explicitly special-cased in the spec.

There is a spec which says both Range#include? and Range#cover? use <=>, but it is only tested with Integers, for which we know from the ominous documentation above that Range#include? and Range#cover? behave the same.

There is quite a lot of special-casing going on for Ranges and it is not the first time this has led to bugs and/or non-intuitive behavior:

Personally, I am not a big fan of all this special-casing. I assume it is done for performance reasons, but the way to get better performance is not to add weird special cases to the language specification, it is to remove them which makes the language simpler and thus easier to optimize. Or, put another way: at any given point in time, a compiler writer can either spend the time implementing weird special cases or awesome optimizations, but not both. XRuby, Ruby.NET, MacRuby, MagLev, JRuby, IronRuby, TruffleRuby, Rubinius, Topaz, and friends have shown that the way to get high-performance Ruby is a powerful compiler, not weird hand-rolled special-cased C code.

I would file a bug, if only to get some clarification into the docs and specs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文