Функция, получающая значение из другой функции, считается чистой?

9

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

function getDefaultSeparator() {
    return ':';
}

function process(input, separator) {
    var separator = separator || getDefaultSeparator();

    // Use separator in some logic

    return output;
}

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

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

Agost
источник
5
Существенных различий нет, если только вы не планируете использовать функцию в качестве заполнителя для некоторой логики, которая будет добавлена ​​позже.
Роберт Харви
3
Возможный дубликат Является ли функция немедленно нечистой, если она принимает функцию в качестве параметра? , Вопрос не является точным дубликатом, но ответ должен быть таким же. («Это зависит от чистоты другой функции.»)
jpmc26
1
Использование глобальной константы не делает функцию нечистой. Использование глобального значения, которое вы предполагаете, является константой.
chepner
Кстати, вы можете карри process(с обратным порядком параметров), а затем специализировать функцию карри дляvar processDefault = process(":")
Боб

Ответы:

22

Функция, получающая значение из другой функции, считается чистой?

Это зависит от того, что делает другая функция, и что делает вызывающая функция. Примесь заразна, чистота - нет.

Вызов чистой функции не меняет чистоту вызывающей функции. Вызов нечистой функции автоматически делает вызывающую функцию также нечистой.

Итак, в вашем примере это зависит от чистоты той части, которую вы пропустили: если она чистая, то вся функция чистая.

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

Ничего. Функция, которая всегда возвращает одно и то же значение, неотличима от константы. Фактически, именно так моделируются постоянные в λ-исчислении.

Йорг Миттаг
источник
2
«Вызов нечистой функции автоматически делает нечистую и вызывающую функцию». Вы в этом уверены? AFAICS, вызов нечистой функции автоматически не делает нечистоту вызывающей стороны, хотя это может произойти.
дедупликатор
2
@Deduplicator: зависит от того, сколько статического анализа вы можете (беспокоиться) сделать. Конечно, если есть функция, funcкоторая имеет побочные эффекты, когда вы передаете в 0, но не когда вы передаете в 1, то вы можете разумно сказать, что, хотя funcсама она «нечистая», функция, вызывающая ее как func(1)(и игнорирующая возвращаемое значение, давайте скажем) не обязательно нечистый. Вызова funcдостаточно, чтобы «испортить» вызывающую сторону как потенциально нечистую, но испорченная функция может быть доказана в некотором смысле чистой. По крайней мере, в javascript, где чистый / нечистый не определен в языке.
Стив Джессоп
6

Да, это обе чистые функции (при условии, что исключенная часть также чиста), потому что:

  1. Результат зависит только от параметров.
  2. Там нет никаких побочных эффектов.

Обратите внимание, что если бы getDefaultSeparator()не было чистой функции, то ни одна не была process()бы чистой.

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

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

8bittree
источник
1

Как говорят другие, конечно, это все еще чистая функция.

Однако поговорим о проблемах дизайна. Вы правы, пытаясь сделать что-то, чтобы сохранить код СУХИМ, поместив значение только в одном месте. Кроме того, я думаю, что следует учитывать уровень связи, который является подходящим.

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

Вопрос в том, нужно ли это кому-то или нет?

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

Даже если потребитель (-и) и поставщик находятся в разных модулях, но модули имеют версии вместе (например, вы используете минимизатор, так что модули потребителей и поставщика находятся в одном файле), также может применяться YAGNI.

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

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

Эрик Эйдт
источник