Рассмотрение аспектов функционального программирования.

Эта и другие статьи доступны в блоге I Read You Learn

Вот вопрос к вам, приведенный ниже код содержит функцию, которая повторяет букву «А» 10 раз, можете ли вы определить, выполняется ли это функция с жадностью или лениво?

Что ж, мы обернули функцию, выполняющую работу, внутри функции повторителя, поэтому работа фактически не будет выполняться, пока мы не вызовем функцию, которая повторитель возвращает значение, поэтому вызов A() в строке 9 выполняет работу лениво. концепция не сложна, но давайте рассмотрим ее, чтобы полностью понять нетерпеливое и ленивое выполнение.

Почему мы решили вызывать функцию лениво?

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

ПРОТИВ. Недостатком отсрочки выполнения является то, что каждый раз, когда мы вызываем функцию, она будет снова и снова выполнять дорогостоящие вычисления.

Вот обратная сторона ленивой работы: мы можем изменить функцию, чтобы она работала с энтузиазмом.

Теперь, когда мы вызываем функцию repeater, мы сразу же выполняем работу.
переменная str сразу же вычисляет строку «AAAAAAAAAA», когда вызов функции repeater.

ЗА:после того, как мы сделали это один раз, нам не нужно делать это снова.

ПРОТИВ: если бы это также было дорогостоящим вычислением, недостатком была бы ситуация, когда функция никогда не вызывается, поэтому мы тратили время на дорогостоящие вычисления, которые никогда не будем использовать.

Имея преимущества обоих миров

У меня к вам еще один вопрос, есть ли способ изменить код, чтобы функция выполняла работу только один раз и мы не не нужно выполнять работу, если ее не попросили?

Что ж, вот золотая середина между двумя подходами:

Теперь мы откладываем работу до тех пор, пока не решим выполнить функцию в строке 13, и нам больше не придется выполнять работу, как в строке 14, потому что мы кэшировали результат во внутренней переменной str. .

Аспекты функционального программирования

Мы закрыли функцию, которая имеет динамическую переменную с именем str
(красные флажки функционального программирования горят), в начале переменная str не определена и позже мы изменим его значение, чтобы кэшировать результат.

Подождите секунду и подумайте, уверены ли вы, что этот код по-прежнему функционально чист?

Если вы не уверены, позвольте мне помочь вам, ответ находится в строке 14, вы должны спросить себя, сколько раз вызов A() будет возвращать ту же самую строку «AAAAAAAAAA»? хорошо каждый раз, поэтому его функционально чистый.

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

В приведенном выше коде мы использовали функцию под названием memoize. Эта утилита добавляет кэш в обернутую функцию, что делает код более чистым, потому что мы не закрываем никакую переменную, которая переназначается.

Кэшируя результат, мы выигрываем от быстрого и отложенного выполнения.

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

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

Прежде чем запоминать функцию, вы должны спросить себя:

  • сколько раз будет вызываться эта функция?
  • будет ли он вызываться с тем же вводом?

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

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

Давайте закончим с четким определением того, что такое чистый вызов функции.

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

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

Эта статья основана на части курса Кайла Симпсона под названием Functional-Light JavaScript, v3 на Frontend Masters. Я настоятельно рекомендую онлайн-курсы Кайла Симпсона и Frontend Masters, чтобы значительно улучшить свои навыки работы с javascript.

*Код, использованный в этой статье, также взят из курса.

Удачного кодирования!