Это чистая функция?
function test(min,max) {
return Math.random() * (max - min) + min;
}
Насколько я понимаю, чистая функция подчиняется этим условиям:
- Он возвращает значение, вычисленное из параметров
- Он не выполняет никакой работы, кроме вычисления возвращаемого значения.
Если это определение верно, является ли моя функция чистой функцией? Или я неправильно понимаю, что определяет чистую функцию?
javascript
function
pure-function
Киви рупела
источник
источник
Math.random()
который изменяет состояние ГСЧ.test(a,b)
всегда возвращает один и тот же объектRandom(a,b)
(который может представлять разные конкретные числа)? Если вы сохраняетеRandom
символический характер, он чист в классическом смысле, если вы оцениваете его заранее и вводите числа, возможно, как своего рода оптимизация, функция все еще сохраняет некоторую «чистоту».Ответы:
Нет, это не так. При одном и том же вводе эта функция будет возвращать разные значения. И тогда вы не сможете построить «таблицу», которая сопоставляет входные и выходные данные.
Из статьи в Википедии о функции Pure :
Кроме того, еще одна вещь заключается в том, что чистую функцию можно заменить таблицей, которая представляет отображение ввода и вывода, как описано в этом потоке .
Если вы хотите переписать эту функцию и изменить ее на чистую функцию, вы также должны передать случайное значение в качестве аргумента.
а затем назовите его так (например, с 2 и 5 как min и max):
источник
Math.random
?Math.random
вывода); чтобы он был чистым, вам нужно как-то сохранить текущее состояние RNG, повторно заполнить его, вызватьMath.random
и восстановить его до предыдущего состояния.Простой ответ на ваш вопрос - это
Math.random()
нарушение правила №2.Во многих других ответах здесь указано, что наличие
Math.random()
означает, что эта функция не является чистой. Но думаю стоит сказать, почемуMath.random()
портит функции, которые его используют.Как и все генераторы псевдослучайных чисел,
Math.random()
начинается с «начального» значения. Затем он использует это значение в качестве отправной точки для цепочки низкоуровневых манипуляций с битами или других операций, которые приводят к непредсказуемому (но не совсем случайному ) выводу.В JavaScript задействованный процесс зависит от реализации, и, в отличие от многих других языков, JavaScript не дает возможности выбрать начальное значение :
Вот почему эта функция не чистая: JavaScript, по сути, использует неявный параметр функции, который вы не можете контролировать. Он считывает этот параметр из данных, рассчитанных и хранящихся в другом месте, и, следовательно, нарушает правило № 2 в вашем определении.
Если вы хотите сделать эту функцию чистой, вы можете использовать один из альтернативных генераторов случайных чисел, описанных здесь . Назовите этот генератор
seedable_random
. Он принимает один параметр (начальное число) и возвращает «случайное» число. Конечно, это число вовсе не случайно; это однозначно определяется семенем. Вот почему это чистая функция. Выходные данныеseedable_random
являются «случайными» в том смысле, что прогнозировать выходные данные на основе входных данных затруднительно.Чистая версия этой функции должна принимать три параметра:
Для любой данной тройки
(min, max, seed)
параметров это всегда будет возвращать один и тот же результат.Обратите внимание: если вы хотите, чтобы результат
seedable_random
был действительно случайным, вам нужно найти способ рандомизировать начальное число! И любая стратегия, которую вы использовали, неизбежно будет нечистой, потому что она потребует от вас сбора информации из источника, не относящегося к вашей функции. Как мне напоминают mtraceur и jpmc26 , сюда входят все физические подходы: аппаратные генераторы случайных чисел , веб-камеры с крышками линз , коллекторы атмосферного шума - даже лавовые лампы . Все это связано с использованием данных, рассчитанных и сохраненных вне функции.источник
Math.random
бы не использовался ГПСЧ, а вместо этого был реализован аппаратный ГСЧ? Аппаратный ГСЧ на самом деле не имеет состояния в обычном смысле, но он производит случайные значения (и, таким образом, вывод функции по-прежнему отличается независимо от ввода), верно?Чистая функция - это функция, в которой возвращаемое значение определяется только входными значениями без наблюдаемых побочных эффектов.
Используя Math.random, вы определяете его значение не по входным значениям. Это не чистая функция.
источник
источник
Нет, это не чистая функция, потому что ее вывод не зависит только от предоставленного ввода (Math.random () может выводить любое значение), в то время как чистые функции всегда должны выводить одно и то же значение для одних и тех же вводов.
Если функция является чистой, можно безопасно оптимизировать несколько вызовов с одними и теми же входными данными и просто повторно использовать результат более раннего вызова.
PS, по крайней мере, для меня и для многих других, redux сделал популярным термин чистая функция . Прямо из документов redux :
источник
С математической точки зрения ваша подпись не
но
где
environment
может предоставить результатыMath.random()
. И на самом деле генерация случайного значения изменяет среду в качестве побочного эффекта, поэтому вы также возвращаете новую среду, которая не равна первой!Другими словами, если вам нужен какой-либо ввод, который не исходит от начальных аргументов (
<number, number>
части), тогда вам необходимо предоставить среду выполнения (которая в этом примере обеспечивает состояниеMath
). То же самое относится и к другим вещам, упомянутым в других ответах, например ввод-вывод или тому подобное.В качестве аналогии вы также можете заметить, что именно так может быть представлено объектно-ориентированное программирование - если мы скажем, например,
тогда на самом деле мы используем
при этом объект, у которого вызывается метод, является частью среды. А почему
SomeClass
часть результата? Потомуsomething
что состояние России тоже могло измениться!источник
test: <environment, number, number> -> <environment, number>
и должно бытьa.F(b, c)
можно рассматривать как синтаксический сахар дляF(a, b, c)
со специальным правилом для отправки в перегруженные определения наF
основе типаa
(на самом деле Python представляет его именно так). Ноa
по-прежнему является явным в обеих нотациях, тогда как среда в нечистой функции никогда не упоминается в исходном коде.Чистые функции всегда возвращают одно и то же значение для одного и того же ввода. Чистые функции предсказуемы и прозрачны по ссылкам, что означает, что мы можем заменить вызов функции на возвращаемый результат, и это не повлияет на работу программы.
https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md
источник
В дополнение к другим ответам, которые правильно указывают на то, что эта функция недетерминирована, у нее также есть побочный эффект: он заставит будущие вызовы
math.random()
возвращать другой ответ. А генератор случайных чисел, у которого нет этого свойства, обычно выполняет какой-то ввод-вывод, например, чтение со случайного устройства, предоставляемого ОС. Либо запрещено для чистой функции.источник
Нет, это не так. Вы вообще не можете понять результат, поэтому этот фрагмент кода не может быть протестирован. Чтобы сделать этот код тестируемым, вам нужно извлечь компонент, который генерирует случайное число:
Теперь вы можете смоделировать генератор и правильно протестировать свой код:
И в вашем "производственном" коде:
источник
util.Random
, который вы можете заполнить в начале тестового прогона для повторения старого поведения или для нового (но повторяемого) прогона. При многопоточности вы можете сделать это в основном потоке и использовать этоRandom
для заполнения повторяемых локальных потоковRandom
. Однако, насколько я понимаю,test(int,int,Random)
это не считается чистым, так как это изменяет состояние файлаRandom
.Вы бы согласились со следующим:
быть эквивалентным
?
Видите ли, определение pure - это функция, вывод которой не изменяется ни на что, кроме его входов. Если мы скажем, что в JavaScript есть способ пометить функцию как чистую и воспользоваться этим, оптимизатору будет разрешено переписать первое выражение как второе.
У меня есть практический опыт в этом. SQL-сервер разрешен
getdate()
иnewid()
в «чистых» функциях, и оптимизатор будет выводить вызовы по своему желанию. Иногда это было бы глупо.источник