¿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 ningún trabajo más que calcular el valor de retorno
Si esta definición es correcta, ¿es mi función una función pura? ¿O mi comprensión de lo que define una función pura es incorrecta?
javascript
function
pure-function
Kiwi Rupia
fuente
fuente
Math.random()
que cambia el estado del RNG.test(a,b)
siempre devuelve el mismo objetoRandom(a,b)
(que puede representar diferentes números concretos). Si mantieneRandom
simbólico, es puro en el sentido clásico, si lo evalúa temprano y lo pone en números, tal vez como una especie de optimización, la función aún conserva algo de "pureza".Respuestas:
No, no es. Dada la misma entrada, esta función devolverá valores diferentes. Y luego no puede construir una 'tabla' que mapee la entrada y las salidas.
Del artículo de Wikipedia para la función pura :
Además, otra cosa es que una función pura se puede reemplazar con una tabla que representa el mapeo 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
y luego llámelo de esta manera (ejemplo, con 2 y 5 como mínimo y máximo):
fuente
Math.random
?Math.random
producción futura ); para que sea puro, tendría que guardar de alguna manera el estado actual de RNG, reiniciarlo, llamarloMath.random
y restaurarlo al estado anterior.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()
corrompe 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 dan como resultado 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 ninguna forma de seleccionar la semilla :
Es por eso que esta función no es pura: JavaScript esencialmente está usando un parámetro de función implícito sobre el que no tienes control. Está leyendo ese parámetro a partir de datos calculados y almacenados en otro lugar y, por lo tanto, viola la regla n. ° 2 de su definición.
Si desea convertir esto en una función pura, puede usar uno de los generadores de números aleatorios alternativos que se describen aquí . 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. Por eso es una función pura. La salida deseedable_random
es solo "aleatoria" en el sentido de que es difícil predecir la salida basándose en la entrada.La versión pura de esta función necesitaría tomar tres parámetros:
Para cualquier triple de
(min, max, seed)
parámetros, siempre devolverá el mismo resultado.Tenga en cuenta que si desea que la salida de
seedable_random
sea verdaderamente aleatoria, ¡deberá encontrar una manera de aleatorizar la semilla! Y cualquier estrategia que utilizara inevitablemente no sería pura, porque requeriría que recopilara 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.fuente
Math.random
no se usara un PRNG sino que se implementara usando un RNG de hardware? El hardware RNG realmente no tiene estado en el sentido normal, pero produce valores aleatorios (y por lo tanto, la salida de la función sigue siendo diferente independientemente de la entrada), ¿verdad?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.
fuente
fuente
No, no es una función pura porque su salida no depende solo de la entrada proporcionada (Math.random () puede generar cualquier valor), mientras que las funciones puras siempre deben generar el mismo valor para las mismas entradas.
Si una función es pura, es seguro optimizar varias 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 de redux :
fuente
Desde el punto de vista matemático, su firma no es
pero
donde el
environment
es capaz de proporcionar resultadosMath.random()
. Y de hecho, generar el valor aleatorio muta el entorno como 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 los argumentos iniciales (la
<number, number>
parte), entonces debe contar con un entorno de ejecución (que en este ejemplo proporciona el estadoMath
). Lo mismo se aplica a otras cosas mencionadas por otras respuestas, como E / S o tal.Como analogía, también puede notar que así es como se puede representar la programación orientada a objetos, si decimos, por ejemplo,
entonces en realidad estamos usando
con el objeto que tiene su método invocado siendo parte del entorno. ¿Y por qué la
SomeClass
parte de resultado? ¡Porquesomething
el estado también podría haber cambiado!fuente
test: <environment, number, number> -> <environment, number>
lo que debería serloa.F(b, c)
puede verse como un azúcar sintácticoF(a, b, c)
con una regla especial para enviar a definiciones sobrecargadas deF
según el tipo dea
(así es como lo representa Python). Peroa
sigue siendo explícito en ambas notaciones, mientras que el entorno en una función no pura nunca se menciona en el código fuente.Las funciones puras siempre devuelven el mismo valor para la misma entrada. Las funciones puras son predecibles y referenciales transparentes, 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
fuente
Además de las otras respuestas que señalan correctamente cómo esta función no es determinista, también tiene un efecto secundario: hará que futuras llamadas
math.random()
a 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 los dos está prohibido para una función pura.fuente
No, no lo es. No puede averiguar el resultado en absoluto, por lo que este fragmento de código no se puede probar. Para que ese código sea comprobable, debe extraer el componente que genera el número aleatorio:
Ahora, puede burlarse del generador y probar su código correctamente:
Y en su código de "producción":
fuente
util.Random
, que puede sembrar al comienzo de una ejecución de prueba para repetir el comportamiento anterior o para una ejecución nueva (pero repetible). Si es un subproceso múltiple, es posible que pueda hacer esto en el subproceso principal y usarloRandom
para sembrarRandom
s locales de subprocesos repetibles . Sin embargo, según tengo entendido,test(int,int,Random)
no se considera puro ya que altera el estado delRandom
.Estaría bien con lo siguiente:
ser equivalente a
?
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 forma 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 está permitido
getdate()
ynewid()
en funciones "puras" y el optimizador deduplica las llamadas a voluntad. A veces esto haría algo tonto.fuente