La semplice risposta alla tua domanda è che Math.random()
viola la regola n. 2.
Molte altre risposte qui hanno sottolineato che la presenza di Math.random()
significa che questa funzione non è pura. Ma penso che valga la pena spiegare perché Math.random()
contamina le funzioni che lo utilizzano.
Come tutti i generatori di numeri pseudocasuali, Math.random()
inizia con un valore "seme". Quindi utilizza quel valore come punto di partenza per una catena di manipolazioni di bit di basso livello o altre operazioni che risultano in un output imprevedibile (ma non realmente casuale ).
In JavaScript, il processo coinvolto dipende dall'implementazione e, a differenza di molti altri linguaggi, JavaScript fornisce non alcun modo per selezionare il seme :
L'implementazione seleziona il seme iniziale per l'algoritmo di generazione di numeri casuali; non può essere scelto o ripristinato dall'utente.
Ecco perché questa funzione non è pura: JavaScript utilizza essenzialmente un parametro di funzione implicito su cui non hai alcun controllo. Sta leggendo quel parametro dai dati calcolati e memorizzati altrove e quindi viola la regola n. 2 nella tua definizione.
Se si desidera rendere questa funzione pura, è possibile utilizzare uno dei generatori di numeri casuali alternativi descritti qui . Chiama quel generatore seedable_random
. Richiede un parametro (il seme) e restituisce un numero "casuale". Naturalmente, questo numero non è affatto casuale; è determinato in modo univoco dal seme. Ecco perché questa è una funzione pura. L'output di seedable_random
è solo "casuale" nel senso che è difficile prevedere l'output in base all'input.
La versione pura di questa funzione dovrebbe prendere tre parametri:
function test(min, max, seed) {
return seedable_random(seed) * (max - min) + min;
}
Per ogni dato triplo di (min, max, seed)
parametri, questo restituirà sempre lo stesso risultato.
Nota che se vuoi che l'output di seedable_random
sia veramente casuale, devi trovare un modo per randomizzare il seme! E qualunque strategia tu abbia usato sarebbe inevitabilmente non pura, perché ti richiederebbe di raccogliere informazioni da una fonte al di fuori della tua funzione. Come mi ricordano mtraceur e jpmc26 , questo include tutti gli approcci fisici: generatori di numeri casuali hardware , webcam con copriobiettivo , raccoglitori di rumore atmosferico e persino lampade lava . Tutto ciò comporta l'utilizzo di dati calcolati e memorizzati al di fuori della funzione.
Math.random()
che cambia lo stato del RNG.