Search code examples
rubyiteratorcodeblockscontrol-flowruby-1.9.1

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.


Solution

  • 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.