Подтвердить что ты не робот

Является ли функция, которая называет Math.random() чистой?

Является ли следующая чистая функция?

function test(min,max) {
   return  Math.random() * (max - min) + min;
}

Я понимаю, что чистая функция следует этим условиям:

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

Если это определение верное, является ли моя функция чистой? Или мое понимание того, что определяет чистую функцию неправильно?

4b9b3361

Ответ 1

Нет, нет. Учитывая тот же ввод, эта функция возвращает разные значения. И тогда вы не можете построить "таблицу", которая отображает входные данные и выходы.

Из статьи в Википедии для Чистая функция:

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

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

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

function test(random, min, max) {
   return random * (max - min) + min;
}

а затем вызовите его таким образом (например, с 2 и 5 как мин и макс):

test( Math.random(), 2, 5)

Ответ 2

Простой ответ на ваш вопрос: Math.random() нарушает правило № 2.

Многие другие ответы здесь указывают на то, что наличие Math.random() означает, что эта функция не является чистой. Но я думаю, что стоит сказать, почему Math.random() использует функции taints, которые его используют.

Как и все генераторы псевдослучайных чисел, Math.random() начинается с значения "семя". Затем он использует это значение в качестве отправной точки для цепи низкоуровневых манипуляций с битами или других операций, которые приводят к непредсказуемому (но не очень случайному) выводу.

В JavaScript этот процесс зависит от реализации, и в отличие от многих других языков, JavaScript предоставляет способ выбора семени:

Реализация выбирает начальное семя для алгоритма генерации случайных чисел; он не может быть выбран или reset пользователем.

Вот почему эта функция не чиста: JavaScript по сути использует неявный функциональный параметр, который вы не контролируете. Он считывает этот параметр из данных, вычисленных и сохраненных в другом месте, и поэтому нарушает правило №2 в вашем определении.

Если вы хотите сделать это чистой функцией, вы можете использовать один из альтернативных генераторов случайных чисел, описанный здесь здесь. Вызовите этот генератор seedable_random. Он принимает один параметр (семя) и возвращает "случайное" число. Конечно, это число действительно не случайное; он однозначно определяется семенем. Вот почему это чистая функция. Выходной сигнал seedable_random является только "случайным" в том смысле, что прогнозирование выхода на основе ввода затруднено.

Чистая версия этой функции должна принимать три параметра:

function test(min, max, seed) {
   return  seedable_random(seed) * (max - min) + min;
}

Для любой заданной тройки параметров (min, max, seed) это всегда возвращает тот же результат.

Обратите внимание, что если вы хотите, чтобы вывод seedable_random был действительно случайным, вам нужно найти способ рандомизировать семя! И любая стратегия, которую вы использовали, неизбежно будет нечистой, потому что это потребует от вас сбора информации из источника вне вашей функции. Поскольку mtraceur и jpmc26 напоминают мне, это включает в себя все физические подходы: аппаратные генераторы случайных чисел, веб-камеры с крышками объективов, атмосферные шумоглушители - даже лавовые лампы. Все это связано с использованием данных, вычисленных и сохраненных вне функции.

Ответ 3

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

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

источник

Ответ 4

Нет, это не чистая функция, потому что ее вывод не зависит только от введенного ввода (Math.random() может выводить любое значение), тогда как чистые функции всегда должны выводить одно и то же значение для тех же самых входов.

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

P.S для меня, по крайней мере, и для многих других, redux сделал термин чистой функции популярным. Прямо из документов redux:

Вещи, которые вы никогда не должны делать внутри редуктора:

  • Мутировать свои аргументы,

  • Выполнять побочные эффекты, такие как вызовы API и переходы маршрутизации;

  • Вызов нечистых функций, например. Date.now() или Math.random().

Ответ 5

С математической точки зрения ваша подпись не

test: <number, number> -> <number>

но

test: <environment, number, number> -> <environment, number>

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

Другими словами, если вам нужен какой-либо вход, который не исходит из начальных аргументов (часть <number, number>), вам необходимо предоставить среду исполнения (которая в этом примере предоставляет состояние для Math), То же самое относится к другим вещам, упомянутым в других ответах, таких как I/O или тому подобное.


Как аналогия, вы также можете заметить, что объектно-ориентированное программирование может быть представлено - если мы скажем, например,

SomeClass something
T result = something.foo(x, y)

то на самом деле мы используем

foo: <something: SomeClass, x: Object, y: Object> -> <SomeClass, T>

с объектом, для которого его метод вызван как часть среды. И почему результат SomeClass результата? Потому что состояние something также может быть изменено!

Ответ 6

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

https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md

Ответ 7

В дополнение к другим ответам, в которых правильно указывается, как эта функция не является детерминированной, она также имеет побочный эффект: она вызовет будущие вызовы math.random(), чтобы вернуть другой ответ. Генератор случайных чисел, который не имеет этого свойства, обычно выполняет какой-то ввод-вывод, например, для чтения с произвольного устройства, предоставляемого ОС. Либо это verboten для чистой функции.

Ответ 8

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

function test(min, max, generator) {
  return  generator() * (max - min) + min;
}

Теперь вы можете издеваться над генератором и правильно проверить свой код:

const result = test(1, 2, () => 3);
result == 4 //always true

И в вашем "производственном" коде:

const result = test(1, 2, Math.random);

Ответ 9

Вы будете в порядке со следующим:

return ("" + test(0,1)) + test(0,1);

эквивалентно

var temp = test(0, 1);
return ("" + temp) + temp;

?

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

У меня есть практический опыт в этом. SQL-сервер разрешил getdate() и newid() в "чистых" функциях, и оптимизатор по умолчанию будет дедуксировать. Иногда это делало бы что-то немым.