Почему мы должны вызывать to_a для объекта перечислителя? - PullRequest
0 голосов
/ 23 сентября 2018

Сцепление each_slice и to_a смущает меня.Я знаю, что each_slice является членом Enumerable и поэтому может вызываться для перечислимых объектов, таких как массивы, а chars возвращает массив символов.

Я также знаю, что each_slice будет разрезать массивв группах из n элементов, что в приведенном ниже примере равно 2.И если блок не передан each_slice, то он возвращает объект Enumerator.

'186A08'.chars.each_slice(2).to_a

Но почему мы должны вызывать to_a для объекта перечислителя, если each_slice уже сгруппировал массив по n элементам?Почему ruby ​​просто не оценивает, что такое объект перечислителя (который представляет собой набор из n элементов)?

1 Ответ

0 голосов
/ 23 сентября 2018

Цель счетчиков - ленивая оценка.Когда вы вызываете each_slice, вы возвращаете объект перечислителя.Этот объект не рассчитывает весь сгруппированный массив заранее.Вместо этого он рассчитывает каждый «срез» по мере необходимости.Это помогает сэкономить память, а также дает вам немного гибкости в вашем коде.

В этом посте о переполнении стека содержится много информации, которую вы найдете полезной:

Какова цель класса Enumerator в Ruby

Чтобы дать вам краткий и сухой ответ на ваш вопрос «Почему я должен звонить to_a, когда ...», ответ - нет.Он еще не перебрал массив.До сих пор он просто определил объект, который говорит, что когда он проходит через массив, вам понадобятся элементы по два за раз.Затем вы можете либо заставить его выполнить вычисления для всех элементов перечислимого (вызывая to_a), либо вы можете альтернативно использовать next или each, чтобы пройти, а затем остановиться на полпути (возможно, рассчитать только половину).из них в отличие от вычисления их всех и отбрасывания второй половины).

Это похоже на то, как класс Range не создает список элементов в диапазоне.(1..100000) не создает массив из 100000 чисел, но вместо этого определяет объект с минимальным и максимальным значениями, и с ним можно выполнять определенные операции.Например (1..100000) .cover? (5) не создает массивный массив, чтобы увидеть, есть ли там это число, а просто видит, больше ли 5 ​​или равно 1 и меньше или равно 100000.

Целью всего этого является производительность и гибкость.

Возможно, стоит подумать, действительно ли вашей реализации необходимо создать массив заранее или вы действительно можете снизить потребление ОЗУ.немного, перебирая перечислитель.(Если ваш реальный сценарий такой же простой, как вы описали, перечислитель мало чем поможет, но если массив на самом деле большой, перечислитель может вам сильно помочь).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...