Es una función que llama a Matemáticas.random () pure?


¿Es lo siguiente una función pura?

function test(min,max) {
   return  Math.random() * (max - min) + min;
}

Mi entendimiento es que una función pura sigue estas condiciones:

  1. Devuelve un valor calculado a partir de los parámetros
  2. No hace otro trabajo que calcular el valor devuelto

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?

Author: coldspeed, 2017-10-31

9 answers

No, no lo es. Dada la misma entrada, esta función devolverá diferentes valores. Y entonces no puedes construir una 'tabla' que mapee la entrada y las salidas.

Del artículo de Wikipedia para Función pura :

La función siempre evalúa el mismo valor de resultado dado el mismo valor(s) del argumento. El valor del resultado de la función no puede depender de información oculta o estado que puede cambiar durante la ejecución del programa o entre diferentes ejecuciones de el programa, ni puede depende de cualquier entrada externa de dispositivos de E/S

También, otra cosa es que una función pura puede ser reemplazada por 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 llamarlo de esta manera (ejemplo, con 2 y 5 como min y max):

test( Math.random(), 2, 5)
 178
Author: Christian Benseler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-31 18:17:53

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 utiliza 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 proporciona ninguna manera de seleccionar la semilla :

La implementación selecciona la semilla inicial para el algoritmo de generación de números aleatorios; no puede ser elegida o restablecida 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 que no tienes control sobre. Está leyendo ese parámetro de datos calculados y almacenados en otro lugar, y por lo tanto viola la regla #2 en su definición.

Si desea hacer de esta una función pura, podría utilizar uno de los generadores alternativos de números aleatorios descritos aquí. Llama 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 en absoluto; está determinado únicamente por la semilla. Es por eso que este es una función pura. La salida de seedable_random es solo "aleatoria" en el sentido de que predecir la salida basada en la entrada es difícil.

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 dado 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, ¡tendría que encontrar una manera de aleatorizar la semilla! Y cualquiera que sea la estrategia que usaste inevitablemente no sería puro, porque requeriría que recopilaras información de una fuente fuera de tu función. Como mtraceur y jpmc26 me recuerdan, esto incluye todos los enfoques físicos: generadores de números aleatorios de hardware, webcams con tapas de lentes, colectores de ruido atmosférico even incluso lámparas de lava . Todos estos implican el uso de datos calculados y almacenados fuera de la función.

 48
Author: senderle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-02 12:55:25

Una función pura es una función donde el valor de retorno solo está determinado por sus valores de entrada, sin efectos secundarios observables

Usando Matemáticas.al azar, usted está determinando su valor por algo que no sea valores de entrada. No es una función pura.

Fuente

 38
Author: TKoL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-31 13:50:55

No, no es una función pura porque su salida no depende solo de la entrada provista (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 múltiples llamadas con las mismas entradas y simplemente reutilizar el resultado de una llamada anterior.

P. S. por lo menos para mí y para muchos otros, redux hizo el término función pura popular. Directamente desde 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;

  • Llamar a funciones no puras, por ejemplo, Date.ahora () o Matemáticas.aleatorio().

 25
Author: Shubhnik Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-05 10:58:50

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 realmente 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 cualquier tipo de entrada que no provenga de argumentos iniciales (la parte <number, number>), entonces debe tener un entorno de ejecución (que en este ejemplo proporciona estado para Math). Lo mismo se aplica a otras cosas mencionadas en otras respuestas, como I / O 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,

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 siendo parte del entorno. ¿Y por qué la parte SomeClass del resultado? Porque something ' s estado podría haber cambiado también!

 20
Author: Adam Kotwasinski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-02 16:42:16

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

 11
Author: Rishabh Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-27 17:44:38

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 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. Es verboten para una función pura.

 9
Author: Davislor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-01 04:25:51

No, no lo es. No se puede averiguar el resultado en absoluto, por lo que este fragmento de código no se puede probar. Para hacer que ese código sea comprobable, necesita 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);
 7
Author: Héctor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-31 12:27:24

Estaría 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 tenía una forma de etiquetar una función pura y aprovechar esto, al optimizador se le permitiría reescribir la primera expresión como la segunda.

Tengo experiencia práctica con esto. SQL server permitido getdate() y newid() en funciones "puras" y el optimizador de la deduplicación llamadas a voluntad. A veces esto haría algo tonto.

 2
Author: Joshua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-03 01:59:17