В примере из документации они установили метод repeat
, который будет принимать перечислимое значение и давать его значения n
раз. Итак, для массива:
array = [1, 2, 3, 4, 5]
вызов repeat(3)
даст:
1
1
1
2
2
2
...
Итак, у меня есть array
и вызов enum = array.repeat(3)
, и теперь я хочу знать, как много элементов в enum
. Я мог бы go пройти и настроить счетчик:
counter = 0; array.repeat(3) { |element| counter += 1 }
и знать, что в enum
есть 15 элементов, или я не являюсь компьютером и обладаю предварительными знаниями о том, что делает repeat
Я мог бы просто сказать array.size * 3
и получить 15.
Но это все излишне, потому что Enumerator
имеет метод size
, поэтому было бы неплохо, если бы я мог просто скажем enum.size
. Тем не менее, размер просто возвращает nil
, потому что он не может вычислить размер лениво, поэтому я должен был бы использовать count
, который просто будет перебирать и подсчитывать элементы, как наше наивное решение. Я могу сказать size
, как лениво вычислять размер, передавая блок в enum_for
(вырезано из документов)
to_enum(__method__, n) do # __method__ is :repeat here
sz = size # Call size and multiply by n...
sz * n if sz # but return nil if size itself is nil
end
и теперь он ведет себя как наш второй метод. Для варианта использования, подобного этому, это может показаться лишь незначительным выигрышем, но если я повторю массив из 1000 элементов 1 миллион раз? Или что, если мой enum работает с внешним сервисом или выполняет много дорогих вычислений? эта небольшая оптимизация могла бы сэкономить немало циклов и избежать ненужной работы, когда все, что вам нужно было всего.