La mayoría de las fuentes definen una función pura como si tuviera las siguientes dos propiedades:
Es la primera condición que me preocupa. En la mayoría de los casos, es fácil juzgar. Considere las siguientes funciones de JavaScript (como se muestra en este artículo )
Puro:
const add = (x, y) => x + y; add(2, 4); // 6Impuro:
let x = 2; const add = (y) => { return x += y; }; add(4); // x === 6 (the first time) add(4); // x === 10 (the second time)Es fácil ver que la segunda función dará diferentes salidas para llamadas posteriores, violando así la primera condición. Y por lo tanto, es impuro.
Esta parte la tengo.
Ahora, para mi pregunta, considere esta función que convierte una cantidad dada en dólares a euros:
(EDITAR: usar const en la primera línea. Se usó let antes sin darse cuenta).
const exchangeRate = fetchFromDatabase(); // evaluates to say 0.9 for today; const dollarToEuro = (x) => { return x * exchangeRate; }; dollarToEuro(100) //90 today dollarToEuro(100) //something else tomorrowSupongamos que obtenemos el tipo de cambio de un db y cambia todos los días.
Ahora, no importa cuántas veces llame a esta función hoy , me dará la misma salida para la entrada 100 . Sin embargo, podría darme una salida diferente mañana. No estoy seguro de si esto viola la primera condición o no.
IOW, la función en sí no contiene ninguna lógica para mutar la entrada, pero se basa en una constante externa que podría cambiar en el futuro. En este caso, es absolutamente seguro que cambiará a diario. En otros casos, podría suceder; puede que no
¿Podemos llamar a tales funciones funciones puras? Si la respuesta es NO, ¿cómo podemos refactorizarla para que sea una?
El valor de retorno de dollarToEuro depende de una variable externa que no es un argumento; por lo tanto, la función es impura.
Si la respuesta es NO, ¿cómo podemos refactorizar la función para que sea pura?
Una opción es pasar tipo de exchangeRate . De esta manera, cada vez que los argumentos son (something, somethingElse) , se garantiza que la salida sea something * somethingElse :
const exchangeRate = fetchFromDatabase(); // evaluates to say 0.9 for today; const dollarToEuro = (x, exchangeRate) => { return x * exchangeRate; }; Tenga en cuenta que para la programación funcional, debe evitar let : use siempre const para evitar la reasignación.
Una respuesta de un yo-purista (donde "yo" es literalmente yo, ya que creo que esta pregunta no tiene una sola respuesta "correcta" formal ):
En un lenguaje tan dinámico como JS con tantas posibilidades de parchear tipos base o crear tipos personalizados usando funciones como Object.prototype.valueOf , es imposible saber si una función es pura con solo mirarla, ya que depende del llamante sobre si quiere producir efectos secundarios.
Una demostración:
const add = (x, y) => x + y; function myNumber(n) { this.n = n; }; myNumber.prototype.valueOf = function() { console.log('impure'); return this.n; }; const n = new myNumber(42); add(n, 1); // this call produces a side effectUna respuesta de mí-pragmático:
De la definición misma de wikipedia.
En programación de computadoras, una función pura es una función que tiene las siguientes propiedades:
- Su valor de retorno es el mismo para los mismos argumentos (sin variación con variables estáticas locales, variables no locales, argumentos de referencia mutables o flujos de entrada de dispositivos de E/S).
- Su evaluación no tiene efectos secundarios (sin mutación de variables estáticas locales, variables no locales, argumentos de referencia mutables o flujos de E/S).
En otras palabras, solo importa cómo se comporta una función, no cómo se implementa. Y siempre que una función en particular tenga estas 2 propiedades, es pura independientemente de cómo se implementó exactamente.
Ahora a su función:
const exchangeRate = fetchFromDatabase(); // evaluates to say 0.9 for today; const dollarToEuro = (x, exchangeRate) => { return x * exchangeRate; }; Es impuro porque no califica el requisito 2: depende transitivamente del IO.
Acepto que la declaración anterior es incorrecta, consulte la otra respuesta para obtener más detalles: https://stackoverflow.com/a/58749249/251311
Otros recursos relevantes: