根据 my_times 定义 my_each

defining my_each in terms of my_times

我正在阅读 The Well-Grounded Rubyist 并且遇到了一个没有答案的额外信用挑战。

class Array
  def my_each
    c = 0
    until c == size
      yield(self[c])
      c += 1
    end
    self
  end
end

给出了创建 my_eachmy_times

的示例
class Array
  def my_each
    size.my_times do |i|
      yield self[i]
    end
    self
  end
end

重点是 Ruby 的许多迭代器都建立在 each 之上,而不是相反。

鉴于上述 my_each,我如何在 my_times 的实现中使用它?

为了说清楚,之前给出了一个my_times实现的例子:

class Integer
  def my_times
    c = 0
    until c == self
      yield(c)
      c += 1
    end
    self
  end
end

5.my_times { |e| puts "The block just got handed #{e}." }

所以看起来这个问题肯定意味着在 my_times.

的实现中使用 my_each

要使用 my_each 实现 my_times,您需要做的就是在看起来像 [0, 1, ..., (x - 1)] 的数组上调用 my_each,其中 xself(整数):

class Integer
  def my_times(&block)
    (0...self).to_a.my_each do |n|
      yield n
    end
    self
  end
end

P.S。如果您在 Enumerable 而不是 Array 上定义了 my_each(如 "real" each),您可以从上面的第三行中删除 to_a 并直接遍历范围,而不是首先将范围转换为数组。

编辑:我刚刚注意到 Jordan used ... instead of .. which generates the correct output; See this answer 以获取有关范围差异的更多详细信息。我在下面更新了我的答案。

我的账户太新了,我无法评论Jordan的解决方案;我看到这是大约一年前发布的,但我目前正在通读 The Well-Grounded Rubyist 并想对解决方案发表评论。

我已经接近它与乔丹相同以类似的方式但发现输出是关闭的至Well-Grounded Rubyist my_times 的实现, 产生:

puts 5.my_times { |i| puts "I'm on iteration # {i}!" }
I'm on iteration 0!
I'm on iteration 1!
I'm on iteration 2!
I'm on iteration 3!
I'm on iteration 4!

Jordan 的解决方案输出:

puts 5.my_times { |i| puts "I'm on iteration # {i}!" }
I'm on iteration 0!
I'm on iteration 1!
I'm on iteration 2!
I'm on iteration 3!
I'm on iteration 4!
I'm on iteration 5!

我使用了一个幻数来匹配 The Well-Grounded Rubyist 输出 [参见 Jordan 的解决方案,使用 ... 而不是 .. 这消除了对幻数的需要]

class Integer
  def my_times
    (0..(self-1)).to_a.my_each do |n|
      yield n
    end
    self
  end
end

为了实现my_times,我们需要一个数组来发送my_each消息。在这本书的那一点上,我认为范围没有涵盖,所以我在没有使用范围的情况下实现了。这是解决方案:

require_relative "my_each"
class Integer
  def my_times
    array = Array.new(self)
    c = 0
    array.my_each do
      array[c] = c
      yield(c)
      c += 1
    end
    self
  end
end