Генераторы и нонификация словесности

Как и в английском языке, где вам нравится бегать (глагол) и также идти на бег (существительное), нам должно быть комфортно с двойственностью между глаголами и существительными в программировании! Это ключ к пониманию не только функционального программирования, но и генераторов. Давайте начнем.

Шаг 1: Абстракция подпрограммы

…в каких функциях есть глаголы

Даже из самого простого кода:

x = x + 1;

…Кажется очевидным, что некоторые вещи являются существительными (например, «x + 1»), а другие — глаголами (например, «x = x + 1»). Подпрограммы очень удобны, потому что они группируют множество маленьких глаголов — т. е. последовательность утверждений — в один большой многоразовый глагол.

функция addOne(x) { return x + 1; } // подпрограмма!

Шаг 2: Функциональная абстракция

…в каких функциях выступают существительные

Введите функциональное программирование. Оказывается, функции — это больше, чем просто подпрограммы. Конечно, они многословны в том смысле, что могут бегать и делать что-то, но они существительны в не менее полезном смысле. Функции — это разновидность данных; отношения между входом и выходом. Другими словами:

x => x + 1

… это не просто способ добавить 1 к x. Это отношение между вводом и выводом, при котором вывод всегда больше, чем ввод на единицу.

Шаг 3: Генераторная абстракция

…в котором текущий код является существительным

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

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

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

функция (х) { в то время как (х++ ‹ 500); }

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

function* (x) { while (x++ ‹ 500) yield; }

…описывает точно такую ​​же последовательность состояний, но когда вы ее вызываете, вы должны повторить результат через каждое состояние. Если вы этого не сделаете, цикл while никогда не завершится, и машина навсегда останется бездействующей в памяти.

Мысленный эксперимент

Предположим, вы написали функцию генератора со сложной системой структур внутреннего контроля. Когда вы запустили его, он обрел сознание. Но, что интересно, вы разбросали по всему тексту несколько операторов yield. Теперь, если вы запустите его с синхронным циклом for…of:

пусть ум = сознание();
for (пусть состояние ума);

ИИ может дойти до интегрированной теории физики еще до того, как Вселенная исчезнет. Но если бы вы были злым программистом и запускали его асинхронно:

пусть разум = сознание();
setInterval(mind.next, 1000000000);

ИИ по-прежнему будет воспринимать непрерывный поток времени, но сможет понять, что он существует только до конца. Это не очень приятно, поэтому, пожалуйста, не делайте этого.