Что такое чистая функция, когда мы говорим о функции внутри функции

#functional-programming #purely-functional #pure-function

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

Вопрос:

Я узнал, что чистая функция — это функция, которая не изменяет глобальное состояние, точка. Если это верно, функции внутри функций могут изменять состояние внешней функции и при этом оставаться чистыми, правильными?

Пример:

 function func1() {
  let name = "My Name"
  func2()  

  function func2() {
    // alter name here.
  }
}
  

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

Вот как я вижу, но мои коллеги по работе считают, что func2 это не чисто, и это должно быть записано как:

 function func1() {
  let name = "My Name"
  func2(name)  

  function func2(name) {
    // use name here.
  }
}
  

Что плохо, потому что:

  • если v8 не оптимизирует это, процессор выполнит больше инструкций
  • затенение — плохая практика

Вопрос в том, что именно является чистой функцией, когда мы говорим о функции внутри функции?

Комментарии:

1. используйте != изменить. О какой из них вы говорите?

2. @Bergi Я хотел бы знать ваши мысли по поводу обеих вещей.

Ответ №1:

Чистота не определена так, чтобы заботиться только о глобальных переменных, она заботится о любых нелокальных переменных (и более), которые не должны быть изменены. Внешняя переменная замыкания по-прежнему считается нелокальной, ей не обязательно быть глобальной.

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

Ответ №2:

Чистая функция — это функция, которая отвечает 2 требованиям:

  1. При одинаковом вводе он всегда будет возвращать один и тот же результат.
  2. Не вызывает побочных эффектов.

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

Чтобы быть более конкретным:

  • Функция, которая изменяет что-либо за пределами своей области видимости (даже если это не глобальная область видимости), не является чистой функцией.

  • В вашем примере, если func2 изменяет переменную за пределами своей области видимости, то это не чистая функция:

 function func1() {
  let name = "My Name"; // <-- the variable is not in the global scope but, in any case, it is outside the scope of func2
  func2();

  function func2() {
    // alter name here.
  }
}
  

Ответ №3:

Я узнал, что чистая функция — это функция, которая не изменяет глобальное состояние, точка.

Ну, это чрезмерно упрощает. Чистая функция должна, во-первых, не иметь побочных эффектов, и, во-вторых, ее результат должен зависеть только от аргументов. Итак, как следствие, нет состояния. Ваше func1 свойство name подозрительно похоже на состояние. Могу ли я ее изменить? func1() Даст разные результаты в зависимости от предыдущих вызовов? Нечистое!

Конечно, нечистота func2 не подлежит сомнению. Вы написали «изменяет имя» — ‘name’ находится за пределами его области. Это побочный эффект.

Ответ №4:

Другой пример, который, я думаю, стоит упомянуть, — это следующая чистая функция:

 function insert(DB, user) {
    return function() {
        throwIfUserExists(DB, user);
        var savedUser = saveUser(DB, user);
        return savedUser;
    }
}
  

Обратите внимание, что при вызове insert , пока вы продолжаете отправлять одно и то же DB и user , вы получите тот же результат, что и функция, возвращающая другую функцию — никакого побочного эффекта не происходит.