如何为 Range 创建自定义迭代器

发布于 2024-12-07 14:16:14 字数 1100 浏览 1 评论 0原文

我想创建 Range 的子类,以便指定 1 以外的步长,这样我就可以执行以下操作:

>> a = RangeWithStepSize.new(-1, 2, 0.5).each {|x| puts(x)}
-1.0
-0.5
0.0
0.5
1.0
1.5
2.0
=> -1..2

我第一次尝试实现不起作用:

 class RangeWithStepSize < Range

  attr_reader :step_size

  def initialize(start_v, end_v, step_size, exclusive = false)
    super(start_v, end_v, exclusive)
    @step_size = step_size
  end

  def each
    self.step(step_size).each
  end

end

>> a = RangeWithStepSize.new(-1, 2, 0.5).each {|x| puts(x)}
=> #<Enumerator: [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]:each>

看起来 RangeWithStepSize#each 返回一个有效的枚举器,但它没有枚举。知道为什么吗?

>> Range.new(-1, 2).step(0.5).class
=> Array

数组是可枚举的,但它不是枚举器。这是一个文档错误吗?

澄清

我想制作一个封装步长的 Range 版本,这样我就可以这样做:

a = RangeWithStepSize(-1, 2, 0.5)
b = RangeWithStepSize(-1, 2, 0.25)

...所以枚举 a 会产生一个步长大小为 0.5,b 产生 0.25。

I'd like to create a subclass of Range in order to specify a step size other than 1 so I can do things like:

>> a = RangeWithStepSize.new(-1, 2, 0.5).each {|x| puts(x)}
-1.0
-0.5
0.0
0.5
1.0
1.5
2.0
=> -1..2

My first attempt at an implementation doesn't work:

 class RangeWithStepSize < Range

  attr_reader :step_size

  def initialize(start_v, end_v, step_size, exclusive = false)
    super(start_v, end_v, exclusive)
    @step_size = step_size
  end

  def each
    self.step(step_size).each
  end

end

>> a = RangeWithStepSize.new(-1, 2, 0.5).each {|x| puts(x)}
=> #<Enumerator: [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]:each>

It appears that RangeWithStepSize#each is returning a valid enumerator, but it doesn't enumerate. Any idea why?

<aside>This may be related, but I notice is that Range#step without a block does NOT return an enumerator as specified in the documentation; it returns an array instead:

>> Range.new(-1, 2).step(0.5).class
=> Array

An Array is enumerable, but it is not an Enumerator. Is this a documentation bug?</aside>

clarification

I'd like to make a version of Range that encapsulates a step size, so I can do:

a = RangeWithStepSize(-1, 2, 0.5)
b = RangeWithStepSize(-1, 2, 0.25)

... so enumerating on a produces a step size of 0.5 and b produces 0.25.

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

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

发布评论

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

评论(1

临风闻羌笛 2024-12-14 14:16:14

你知道你可以做到这一点,对吧?这里不需要继承。

(-1..2).step(0.5) do |x|
    puts x
end

您的代码只需进行一些小的调整即可工作:

class RangeWithStepSize < Range

  attr_reader :step_size

  def initialize(start_v, end_v, step_size, exclusive = false)
    super(start_v, end_v, exclusive)
    @step_size = step_size
  end

  def each (&block)
    self.step(step_size).each(&block)
  end

end

You know you can do this, right? Inheritance isn't necessary here.

(-1..2).step(0.5) do |x|
    puts x
end

Your code will work with a few small adjustments:

class RangeWithStepSize < Range

  attr_reader :step_size

  def initialize(start_v, end_v, step_size, exclusive = false)
    super(start_v, end_v, exclusive)
    @step_size = step_size
  end

  def each (&block)
    self.step(step_size).each(&block)
  end

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