Определение 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
.