Проста відповідь на ваше запитання полягає в тому, що Math.random()
порушує правило №2.
Багато інших відповідей тут вказували на те, що наявність засобів Math.random()
означає, що ця функція не є чистою. Але я вважаю, що варто сказати, чому Math.random()
заплямовує функції, які його використовують.
Як і всі генератори псевдовипадкових чисел, Math.random()
починається зі значення «насіння». Потім воно використовує це значення як вихідну точку для ланцюжка бітових маніпуляцій низького рівня або інших операцій, які призводять до непередбачуваного (але насправді не випадкового ) виводу.
У JavaScript процес, що займається цим процесом, залежить від реалізації, і на відміну від багатьох інших мов, JavaScript не пропонує способу вибору насіння :
Реалізація вибирає початкове насіння в алгоритм генерації випадкових чисел; користувач не може його вибрати або скинути.
Ось чому ця функція не є чистою: 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 , це включає всі фізичні підходи: апаратні генератори випадкових чисел , веб-камери з кришками об'єктивів , атмосферні колектори шуму - навіть лавові лампи . Усе це включає використання даних, обчислених та збережених поза функцією.
Math.random()
що змінює стан RNG.