numeros - math.round javascript
¿Es una función que llama a Math.random() puro? (9)
Además de las otras respuestas que señalan correctamente cómo esta función no es determinista, también tiene un efecto secundario: causará que futuras llamadas a
math.random()
devuelvan una respuesta diferente.
Y un generador de números aleatorios que no tiene esa propiedad generalmente realizará algún tipo de E / S, como leer desde un dispositivo aleatorio proporcionado por el sistema operativo.
Cualquiera de las dos es verboten para una función pura.
¿Es lo siguiente una función pura?
function test(min,max) {
return Math.random() * (max - min) + min;
}
Tengo entendido que una función pura sigue estas condiciones:
- Devuelve un valor calculado a partir de los parámetros.
- No hace más trabajo que calcular el valor de retorno
Si esta definición es correcta, ¿es mi función una función pura? ¿O es incorrecto mi comprensión de lo que define una función pura?
Desde el punto de vista matemático, su firma no es
test: <number, number> -> <number>
pero
test: <environment, number, number> -> <environment, number>
donde el
environment
es capaz de proporcionar resultados de
Math.random()
.
Y, de hecho, generar el valor aleatorio muta el entorno como un efecto secundario, por lo que también devuelve un nuevo entorno, ¡que no es igual al primero!
En otras palabras, si necesita algún tipo de entrada que no provenga de argumentos iniciales (la parte
<number, number>
), entonces debe contar con un entorno de ejecución (que en este ejemplo proporciona el estado para
Math
).
Lo mismo se aplica a otras cosas mencionadas por otras respuestas, como E / S o similares.
Como analogía, también puede notar que así es como se puede representar la programación orientada a objetos, si decimos, por ejemplo
SomeClass something
T result = something.foo(x, y)
entonces en realidad estamos usando
foo: <something: SomeClass, x: Object, y: Object> -> <SomeClass, T>
con el objeto que tiene su método invocado como parte del entorno.
¿Y por qué la parte
SomeClass
del resultado?
¡Porque el estado de
something
podría haber cambiado también!
Estarías bien con lo siguiente:
return ("" + test(0,1)) + test(0,1);
ser equivalente a
var temp = test(0, 1);
return ("" + temp) + temp;
?
Verá, la definición de puro es una función cuya salida no cambia con nada más que sus entradas. Si decimos que JavaScript tiene una manera de etiquetar una función pura y aprovechar esto, el optimizador podría reescribir la primera expresión como la segunda.
Tengo experiencia práctica con esto.
El servidor SQL permitió
getdate()
y
newid()
en funciones "puras" y el optimizador deduciría las llamadas a voluntad.
A veces esto haría algo tonto.
La respuesta simple a su pregunta es que
Math.random()
viola la regla # 2.
Muchas otras respuestas aquí han señalado que la presencia de
Math.random()
significa que esta función no es pura.
Pero creo que vale la pena decir
por qué
Math.random()
contamina las funciones que lo usan.
Como todos los generadores de números pseudoaleatorios,
Math.random()
comienza con un valor "semilla".
Luego usa ese valor como punto de partida para una cadena de manipulaciones de bits de bajo nivel u otras operaciones que resultan en una salida impredecible (pero no realmente
aleatoria
).
En JavaScript, el proceso involucrado depende de la implementación y, a diferencia de muchos otros lenguajes, JavaScript no proporciona forma de seleccionar la semilla :
La implementación selecciona la semilla inicial para el algoritmo de generación de números aleatorios; no puede ser elegido o restablecido por el usuario.
Es por eso que esta función no es pura: JavaScript está esencialmente usando un parámetro de función implícito sobre el que no tiene control. Está leyendo ese parámetro a partir de datos calculados y almacenados en otro lugar, y por lo tanto viola la regla # 2 en su definición.
Si desea hacer de esto una función pura, puede usar uno de los generadores alternativos de números aleatorios descritos
here
.
Llame a ese generador
seedable_random
.
Toma un parámetro (la semilla) y devuelve un número "aleatorio".
Por supuesto, este número no es realmente aleatorio;
está determinado únicamente por la semilla.
Es por eso que esta es una función pura.
La salida de
seedable_random
es solo "aleatoria" en el sentido de que es difícil predecir la salida en función de la entrada.
La versión pura de esta función necesitaría tomar tres parámetros:
function test(min, max, seed) {
return seedable_random(seed) * (max - min) + min;
}
Para cualquier triple de parámetros
(min, max, seed)
, esto siempre devolverá el mismo resultado.
Tenga en cuenta que si desea que la salida de
seedable_random
sea
verdaderamente
aleatoria, ¡deberá encontrar una forma de aleatorizar la semilla!
Y cualquier estrategia que use inevitablemente no será pura, porque requeriría que recopile información de una fuente fuera de su función.
Como me recuerdan
mtraceur
y
jpmc26
, esto incluye todos los enfoques físicos:
generadores de números aleatorios de hardware
,
cámaras web con tapas de lentes
,
colectores de ruido atmosférico
, incluso
lámparas de lava
.
Todo esto implica el uso de datos calculados y almacenados fuera de la función.
Las funciones puras siempre devuelven el mismo valor para la misma entrada. Las funciones puras son predecibles y son transparentes referenciales, lo que significa que podemos reemplazar la llamada a la función con la salida devuelta y no cambiará el funcionamiento del programa.
https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md
No lo es. No puede determinar el resultado en absoluto, por lo que este código no se puede probar. Para que el código sea comprobable, debe extraer el componente que genera el número aleatorio:
function test(min, max, generator) {
return generator() * (max - min) + min;
}
Ahora, puedes burlarte del generador y probar tu código correctamente:
const result = test(1, 2, () => 3);
result == 4 //always true
Y en su código de "producción":
const result = test(1, 2, Math.random);
No, no es una función pura porque su salida no depende solo de la entrada proporcionada (Math.random () puede emitir cualquier valor), mientras que las funciones puras siempre deben emitir el mismo valor para las mismas entradas.
Si una función es pura, es seguro optimizar múltiples llamadas con las mismas entradas y simplemente reutilizar el resultado de una llamada anterior.
PD: al menos para mí y para muchos otros, redux hizo popular el término función pura . Directamente de los documentos redux :
Cosas que nunca debes hacer dentro de un reductor:
Mutar sus argumentos;
Realizar efectos secundarios como llamadas API y transiciones de enrutamiento;
Llame a funciones no puras, por ejemplo, Date.now () o Math.random ().
No, no es. Dada la misma entrada, esta función devolverá valores diferentes. Y luego no se puede construir una ''tabla'' que mapee la entrada y las salidas.
Del artículo de Wikipedia para la función Pura :
La función siempre evalúa el mismo valor de resultado dados los mismos valores de argumento. El valor del resultado de la función no puede depender de ninguna información oculta o estado que pueda cambiar mientras se ejecuta la ejecución del programa o entre diferentes ejecuciones del programa, ni puede depender de ninguna entrada externa de dispositivos de E / S
Además, otra cosa es que una función pura se puede reemplazar con una tabla que representa la asignación de la entrada y la salida, como se explica en este hilo .
Si desea reescribir esta función y cambiarla a una función pura, también debe pasar el valor aleatorio como argumento
function test(random, min, max) {
return random * (max - min) + min;
}
y luego llámalo de esta manera (ejemplo, con 2 y 5 como min y max):
test( Math.random(), 2, 5)
Una función pura es una función en la que el valor de retorno solo está determinado por sus valores de entrada, sin efectos secundarios observables
Al usar Math.random, está determinando su valor por algo diferente a los valores de entrada. No es una función pura.