JavaScript. Подробное руководство, 6-е издание, стр. 154
<b>// Сконструировать конвейер генераторов для обработки текста.</b><b>// Сначала разбить текст на строки</b><b>let lines = eachline(text);</b><b>// Затем удалить начальные и конечные пробелы в каждой строке</b><b>let trimmed = map(lines, function(line) { return line.trim(); });</b><b>// Наконец, игнорировать пустые строки и комментарии</b><b>let nonblank = select(trimmed, function(line) {</b><b> return line.length > 0 && 1ine[0] !=</b><b>});</b><b>// Теперь извлечь отфильтрованные строки из конвейера и обработать их,</b><b>// остановиться, если встретится строка “quit",</b><b>for (let line in nonblank) {</b><b> if (line === "quit") break; console.log(line);</b><b>}</b>Обычно инициализация генераторов выполняется при их создании: аргументы, передаваемые функции-генератору, являются единственными значениями, которые принимают генераторы. Однако имеется возможность передать дополнительные данные уже работающему генератору. Каждый генератор имеет метод
<b>send(),</b><b>next().</b><b>send()</b><b>yield</b><b>yield</b><b>yield</b><b>next()</b><b>send()</b><b>throw().</b><b>yield</b><b>throw()</b><b>// Функция-генератор, ведущая счет от заданного начального значения.</b><b>// Метод send() позволяет увеличить счетчик на определенное значение.</b><b>// Вызов throw("reset") сбрасывает счетчик в начальное значение.</b><b>// Это всего лишь пример - здесь метод throw() используется не самым лучшим образом, </b><b>function counter(initial) {</b><b> let nextValue = initial; // Сохранить начальное значение</b><b> while(true) {</b><b> try {</b><b> let increment = yield nextValue; // Вернуть значение и получить приращение </b><b> if (increment) // Если передано приращение...</b><b> nextValue += increment; // ...использовать его.</b><b> else nextValue++; // Иначе увеличить на 1</b><b> }</b><b> catch (e) { // Если был вызван метод </b><b> if (e==="reset") // throw() генератора</b><b> nextValue = initial; else throw e;</b><b> }</b><b> }</b><b>}</b><b>let c = counter(10); // Создать генератор с начальным значением 10 </b><b>console.log(c.next()); //Выведет 10</b><b>console.log(c.send(2)); // Выведет 12</b><b>console.log(c.throw("reset")); // Выведет 10</b>11.4.4. Генераторы массивов
Еще одна особенность, заимствованная в JavaScript 1.7 из языка Python, - генераторы массивов. Это механизм инициализации элементов массива на основе элементов другого массива или итерируемого объекта. Синтаксис генераторов массивов основан на математической форме записи элементов множества, т. е. выражения и инструкции находятся совсем не там, где привыкли их видеть программисты на языке JavaScript. Тем не менее привыкание к необычному синтаксису происходит достаточно быстро, а мощь генераторов массивов просто неоценима.
Ниже приводится пример генератора массивов, использующего созданную выше функцию range() для инициализации массива, содержащего квадраты четных чисел, меньшие 100:
<b>let evensquares = [х*х for (х in range(0,10)) if (х % 2 === 0)]</b>Эта строка примерно эквивалентна следующим пяти строкам:
<b>let evensquares = [];</b><b>for(x in range(0,10)) {</b><b> if (x % 2 === 0)</b><b> evensquares.push(x*x);</b><b>}</b>В общем случае синтаксис генераторов массивов имеет следующий вид:
<b>[ выражение for ( переменная in объект ) if ( условное выражение ) ]</b>Обратите внимание на три основные части в квадратных скобках:
• Цикл
<b>for/in</b><b>for/each</b><b>in</b><b>in</b><b>var</b><b>let</b><b>let</b>