Определение my_each с точки зрения my_times

Я читаю "Обоснованный рубин" и столкнулся с дополнительным кредитным испытанием, на которое нет ответа.

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

Приведен пример создания my_each с my_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_each в реализации my_times,

4 ответа

Решение

Реализовать my_times с помощью my_eachвсе, что вам нужно сделать, это позвонить my_each на массиве, который выглядит как [0, 1, ..., (x - 1)], где x является self (целое число):

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

PS Если вы определили my_each на Enumerable вместо Array (как у "настоящих" each), вы можете удалить to_a от третьей строки выше и выполняйте итерацию непосредственно над Range, вместо того, чтобы сначала преобразовывать Range в Array.

Для реализации 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

Редактировать: я только что заметил, Jordan Running использовал ... вместо .. который генерирует правильный вывод; Смотрите этот ответ для более подробной информации о разнице для диапазонов. Я обновил свой ответ ниже.

Моя учетная запись слишком новая, и я не могу комментировать решение Jordan Running; Я вижу, что это было опубликовано около года назад, но в настоящее время я читаю The Well-Gounded Rubyist и хотел прокомментировать решение.

Я подошел к нему так же, как Джордан, но обнаружил, что выходной по сравнению с; Обоснованная реализация 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!

Результаты решения Джордана:

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!

Я использовал магическое число, чтобы соответствовать "Обоснованному выходу Rubyist" [См. Решение Джордана, используя ... вместо .. который устраняет необходимость в магическом числе]

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

Я сократил реализацию dwyd, чтобы предоставить блок, а не использовать do..end.

      class Integer
  def my_times
    (0...self).to_a.my_each { |i| yield i }
  end
end

Кроме того, я не думаю, что вам нужно делатьself-1.

Другие вопросы по тегам