¿Qué Es una Función Pura?
Beneficios
El uso de funciones puras ofrece varios beneficios, tanto en términos de rendimiento como de usabilidad.
Legibilidad
Las funciones puras son mucho más fáciles de leer y razonar. Todas las entradas y dependencias relevantes se proporcionan como parámetros, por lo que no se observan efectos que alteren variables fuera del conjunto de entradas.
Esto significa que podemos entender rápidamente una función y sus dependencias, simplemente leyendo la declaración de la función. Por lo tanto, si una función se declara como f(a, b, c)
entonces sabemos que sólo a
b
y c
son dependencias de f
.
Portabilidad
Como todas las dependencias se proporcionan como parámetros de entrada y no se accede a ellas a través de un contexto global, estas dependencias se pueden intercambiar dependiendo del contexto en el que se llame a la función.
Esto significa que la misma función puede actuar en diferentes implementaciones del mismo recurso, por ejemplo.
Esto hace que el código sea mucho más portátil y reutilizable, ya que la misma función se puede usar en varios contextos, en lugar de tener que escribir una función diferente solo para usar una implementación diferente de la misma clase.
Por ejemplo, en lugar de tener que escribir dos funciones impuras diferentes para usar dos registradores diferentes que se almacenan globalmente, una función pura solo tomaría el registrador deseado como entrada.
Testing
La falta de efectos secundarios hace que las funciones puras sean muy fáciles de probar, ya que solo necesitamos probar que las entradas producen las salidas deseadas. No necesitamos verificar la validez de ningún estado de programa global en nuestras pruebas de funciones específicas.
Además, como todas las dependencias se proporcionan como entradas, podemos simular fácilmente dependencias. En un entorno impuro, tendríamos que hacer un seguimiento del estado de alguna dependencia global a lo largo de todas las pruebas.
Sin embargo, en un entorno puro, simplemente proporcionaríamos todas las dependencias como entrada. Ya no tenemos que preocuparnos por mantener el estado global a lo largo de nuestras pruebas, y ahora podemos proporcionar potencialmente diferentes versiones de dependencias a diferentes pruebas.
Esto nos permite probar funciones mientras tenemos control explícito sobre las dependencias proporcionadas en cada prueba.
Transparencia referencial
La transparencia referencial se refiere a ser capaz de reemplazar la llamada de una función con su valor de salida correspondiente sin cambiar el comportamiento de un programa.
Para lograr transparencia referencial, una función debe ser pura. Esto tiene beneficios en términos de legibilidad y velocidad. Los compiladores a menudo son capaces de optimizar el código que exhibe transparencia referencial.
Almacenamiento en caché
Como las funciones puras siempre devuelven la misma salida para la misma entrada, podemos almacenar en caché los resultados de las llamadas a funciones puras.
El almacenamiento en caché se refiere al uso de una técnica, como la memoización, para almacenar los resultados de las funciones de modo que solo necesitemos calcularlos una vez.
Normalmente, para una función f: Input -> Output
esto se logra a través de un mapa (como un hash-mapa) de Input -> Output
.
Al ejecutar una función, primero comprobamos si el mapa contiene la entrada como una tecla. Si lo hace, devolvemos el valor de salida del mapa, de lo contrario, calculamos f(input)
, y luego almacenamos la salida en el mapa antes de devolverla.