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

时间:2011-09-28 17:47:19

标签: ruby enumerator

我想创建一个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#每个都返回一个有效的枚举器,但它没有枚举。知道为什么吗?

<aside>这可能是相关的,但我注意到没有块的Range#step不会返回文档中指定的枚举器;它返回一个数组:

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

Array是可枚举的,但它不是Enumerator。这是文档错误吗?</aside>

澄清

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

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

...所以枚举a会产生0.5的步长,b会产生0.25。

1 个答案:

答案 0 :(得分:2)

你知道你可以做到这一点,对吗?这里没有必要继承。

(-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