Jonathan Jonathan - 6 months ago 10
Ruby Question

defining my_each in terms of my_times

I'm reading The Well-Grounded Rubyist and have come across an extra credit challenge to which there is no answer.

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


An example is given of creating a
my_each
with
my_times


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


With the point that many of Ruby's iterators are built on top of
each
and not the other way around.

Given the above
my_each
, how could I use it in an implementation of
my_times
?

To make it clear, an example of a
my_times
implementation was given before:

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}." }


So it would seem that the question most certainly implies using
my_each
in an implementation of
my_times
.

Answer

To implement my_times using my_each, all you need to do is call my_each on an array that looks like [0, 1, ..., (x - 1)], where x is self (the Integer):

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

P.S. If you defined my_each on Enumerable instead of Array (like the "real" each), you could remove to_a from the third line above and iterate directly over the Range, instead of converting the Range to an Array first.