Как раз тогда, когда вы думали, что ребенок закончил показывать вам трюки

За последние годы JavaScript получил много негативных отзывов в прессе, но он по-прежнему остается самым доминирующим языком веб-программирования. Была даже написана книга, в которой выделялись только хорошие стороны, в которой предполагалось, что в ней много плохих частей.

Примерно через месяц после начала наших отношений я быстро понял, что между мной и JavaScript не было любви, но я признал ее силу и очарование.

Я начал знакомиться с JavaScript в 2006 году. Тогда я был безумно влюблен в C#, но у нас были трудные времена, поэтому я решил прощупать почву… так сказать. Примерно через месяц после начала наших отношений я быстро понял, что между мной и JavaScript не было любви, но я признал ее силу и очарование.

С появлением Node.js JavaScript стал языком, который можно было использовать не только во внешнем интерфейсе, но и в бэкэнде: для этого используется термин «изоморфный». Это укрепило наши отношения, и с тех пор я использую JavaScript для создания приложений.

Недавно я написал небольшой фреймворк на JavaScript, который использовал генераторы для создания своего рода «конвейера». Во второй части этой статьи будет реализована начальная версия этой библиотеки. Сейчас мы представим ключевое понятие.

Что мы рассмотрим в части I

  1. Нетерпеливое исполнение
  2. Ленивая оценка
  3. Генераторы JavaScript
  4. Предварительная версия: настройка конвейера
  5. Совместимость

Что мы рассмотрим во второй части

  1. Реализация конвейера
  2. Вариант использования: конвейер обработки текста
  3. Принципы программного обеспечения и используемые шаблоны проектирования

Нетерпеливое исполнение

Взгляните на следующий код в JavaScript:

Вызов функции countForever приведет к тому, что программа будет работать вечно. Переменная count, будучи целым числом, имеет конечное число значений, которые она может генерировать, и она будет переполняться, но оператору while все равно. Это просто будет продолжаться вечно.

Да, я знаю, никто в здравом уме не стал бы писать такой код, но я просто хочу подчеркнуть, что суть в следующем: этот код нетерпеливи приведет к зависанию программы .

Что вам нужно, так это возможность контролировать выполнение

Что, если бы это было более практично? Скажем, вы читали миллиарды строк из CSV-файла? Код, который выглядит примерно так, как показано выше, не будет оптимальным. Библиотека Pandas загружает данные таким образом, поэтому ее производительность снижается при больших объемах данных — или, по крайней мере, не без определенных приемов оптимизации или вспомогательных библиотек, помогающих загружать большие файлы.

Что вам нужно, так это возможность контролировать исполнение, а также завершать его на ваших условиях. Здесь нужен генератор. Прежде чем мы дойдем до этого, давайте поговорим о ключевом компоненте генераторов: ленивом вычислении.

Ленивая оценка

Ленивая оценка откладывает выполнение выражения до тех пор, пока оно не понадобится.

Просто правильно! Если вам интересно, «что, черт возьми, это значит?», не волнуйтесь, я продемонстрирую с точностью Робинхуда, что это значит.

Самый простой генератор JavaScript

Приведенная ниже функция, возможно, является простейшим генератором.

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

Метод next() перемещает итератор к следующему значению, а свойство «value»представляет текущий элемент. на который указывает итератор.

Этот код ленив. Вы должны позвать его или сказать, чтобы он что-то сделал, иначе он просто будет лежать, как будто он загорает на карибском пляже. Однако в данном случае лень не является чем-то плохим.

Три вещи, на которые вы должны обратить внимание:
1. Звездочка "*": это говорит функции стать генератором
2. Вызов этой функции возвращает или "дает" один результат в время
3. Звонящий имеет полный контроль

Более авансовый генератор

Помните первую функцию «счет навсегда» выше? Давайте сделаем это ленивым.

Этот код фактически закончится. Как и в случае с «simplestGenerator», три строки кода, вызывающие функцию «countForever», демонстрируют, что управление возвращается звонившему. Результат будет возвращен вызывающей стороне только тогда и только тогда, когда он запрошен, несмотря на цикл.

Вынос

  1. Генераторы позволяют программе быть чрезвычайно эффективной с точки зрения использования памяти. Вы можете обрабатывать бесконечные строки данных и никогда не исчерпаете память, но только если…
  2. ... вы обрабатываете, не просматривая все данные. Если вы собираетесь агрегировать (суммировать, группировать, объединять и т. д.), то генераторы могут оказаться бесполезными в этих случаях.

Предварительная версия: настройка конвейера

Теперь давайте превратим все это во что-то более полезное. Взгляните на диаграмму последовательности ниже:

Диаграмма последовательности говорит о том, что будет поток чисел и будет набор операций для выполнения над числами, в нашем случае две операции: возведение в квадрат и добавить-1. Номера будут обрабатываться по одному. Вот как установка будет выглядеть в коде.

Этот код, хотите верьте, хотите нет, будет вести себя так же, как диаграмма последовательности, показанная выше. Данные будут передаваться от источника массива через операции и обратно к инициатору.

pipeline.execute // this is the initiator

Это может показаться не таким уж большим, но такой конвейер никогда не исчерпает память и может обрабатывать, хотя и только в последовательности, почти бесконечное количество данных. Из-за того, что он работает по принципу «включай и работай», маловероятно, что при добавлении новых функций вы внесете ошибки, и если вы это сделаете, они будут изолированы.

Совместимость с браузером и Node.JS

И последнее замечание: прежде чем вы начнете добавлять генераторы в свой код, имейте в виду, что они могут не поддерживаться в версии JavaScript в вашем браузере или NodeJS. В таблице ниже показаны среды, в которых доступны генераторы.

Быть в курсе

Во второй части этой серии я соберу простую структуру, которая позволяет подключать операции к конвейеру и обрабатывать по одному элементу за раз из потокового источника данных. Я покажу, как я использовал тот же шаблон проектирования для обработки сотен документов в Google Cloud ML для обработки естественного языка. До скорого.

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