En programación de computadoras , una función pura es una función que tiene las siguientes propiedades: [1] [2]
- Los valores de retorno de la función son idénticos para argumentos idénticos (sin variación con variables estáticas locales , variables no locales , argumentos de referencia mutables o flujos de entrada ).
- La aplicación de la función no tiene efectos secundarios (sin mutación de variables estáticas locales, variables no locales, argumentos de referencia mutables o flujos de entrada / salida).
Por tanto, una función pura es un análogo computacional de una función matemática . Algunos autores, particularmente de la comunidad del lenguaje imperativo, usan el término "puro" para todas las funciones que solo tienen la propiedad anterior 2 [3] [4] (discutida a continuación ).
Ejemplos de
Funciones puras
Los siguientes ejemplos de funciones de C ++ son puros:
floor
, devolviendo el piso de un número;max
, devolviendo el máximo de dos valores.- la función f , definida como
void f () { static std :: atomic < unsigned int > x = 0 ; ++ x ; }
- Aunque este ejemplo de código parece no ser puro, en realidad lo es. El valor de
x
sólo puede observarse dentro de otras invocaciones def()
, y comof()
no comunica el valor dex
a su entorno, es indistinguible de la funciónvoid f() {}
que no hace nada. Tenga enx
cuentastd::atomic
que las modificaciones de varios subprocesos que se ejecutanf()
simultáneamente no dan como resultado una carrera de datos , que tiene un comportamiento indefinido en C y C ++.
Funciones impuras
Las siguientes funciones de C ++ son impuras ya que carecen de la propiedad 1 anterior:
- debido a la variación del valor de retorno con una variable estática
int f () { static int x = 0 ; ++ x ; return x ; }
- debido a la variación del valor de retorno con una variable no local
int f () { retorno x ; }
- Por la misma razón, por ejemplo, la función de la biblioteca C ++
sin()
no es pura, ya que su resultado depende del modo de redondeo IEEE que se puede cambiar en tiempo de ejecución.
- debido a la variación del valor de retorno con un argumento de referencia mutable
int f ( int * x ) { retorno * x ; }
- debido a la variación del valor de retorno con un flujo de entrada
int f () { int x = 0 ; estándar :: cin >> x ; return x ; }
Las siguientes funciones de C ++ son impuras ya que carecen de la propiedad 2 anterior:
- debido a la mutación de una variable estática local
void f () { static int x = 0 ; ++ x ; }
- debido a la mutación de una variable no local
vacío f () { ++ x ; }
- debido a la mutación de un argumento de referencia mutable
vacío f ( int * x ) { ++ * x ; }
- debido a la mutación de un flujo de salida
void f () { std :: cout << "¡Hola, mundo!" << std :: endl ; }
Las siguientes funciones de C ++ son impuras ya que carecen de las propiedades 1 y 2 anteriores:
- debido a la variación del valor de retorno con una variable estática local y la mutación de una variable estática local
int f () { static int x = 0 ; ++ x ; return x ; }
- debido a la variación del valor de retorno con un flujo de entrada y la mutación de un flujo de entrada
int f () { int x = 0 ; estándar :: cin >> x ; return x ; }
E / S en funciones puras
La E / S es inherentemente impura: las operaciones de entrada socavan la transparencia referencial y las operaciones de salida crean efectos secundarios. Sin embargo, hay un sentido en el que la función puede realizar entrada o salida y aún ser pura, si la secuencia de operaciones en los dispositivos de E / S relevantes se modela explícitamente como un argumento y un resultado, y las operaciones de E / S se toman para falla cuando la secuencia de entrada no describe las operaciones realmente realizadas desde que el programa comenzó a ejecutarse.
El segundo punto asegura que la única secuencia utilizable como argumento debe cambiar con cada acción de E / S; el primero permite que diferentes llamadas a una función de ejecución de E / S devuelvan resultados diferentes debido a que los argumentos de secuencia han cambiado. [5] [6]
La mónada de E / S es un lenguaje de programación que se utiliza normalmente para realizar E / S en lenguajes funcionales puros.
Optimizaciones del compilador
Las funciones que solo tienen la propiedad 2 anterior permiten técnicas de optimización del compilador, como la eliminación de subexpresiones comunes y la optimización de bucles similares a los operadores aritméticos. [3] Un ejemplo de C ++ es el length
método, que devuelve el tamaño de una cadena, que depende del contenido de la memoria al que apunta la cadena, por lo que carece de la propiedad anterior 1. Sin embargo, en un entorno de un solo subproceso , el siguiente código C ++
std :: string s = "¡Hola, mundo!" ; int a [ 10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; int l = 0 ;para ( int i = 0 ; i < 10 ; ++ i ) { l + = s . longitud () + a [ i ]; }
se puede optimizar de modo que el valor de s.length()
se calcule solo una vez, antes del ciclo.
En Fortran , la pure
palabra clave se puede usar para declarar que una función está libre de efectos secundarios (es decir, que solo tiene la propiedad 2 anterior).
Examen de la unidad
Dado que las funciones puras tienen valores de retorno idénticos para argumentos idénticos , son muy adecuadas para las pruebas unitarias .
Ver también
- Ejecución de funciones en tiempo de compilación: la evaluación de funciones puras en tiempo de compilación
- Algoritmo determinista
- Estructura de datos puramente funcional
- Cálculo lambda
- Efecto secundario (informática)
- Procedimiento puro
- Idempotencia
- palabra clave pura en Fortran que anota funciones puras
- palabra clave constexpr en C ++ que anota funciones puras utilizables en tiempo de compilación
Referencias
- ^ Bartosz Milewski (2013). "Conceptos básicos de Haskell" . Escuela de Haskell . FP completo. Archivado desde el original el 27 de octubre de 2016 . Consultado el 13 de julio de 2018 .
Aquí están las propiedades fundamentales de una función pura: 1. Una función devuelve exactamente el mismo resultado cada vez que se llama con el mismo conjunto de argumentos. En otras palabras, una función no tiene estado ni puede acceder a ningún estado externo. Cada vez que lo llamas, se comporta como un bebé recién nacido con la memoria en blanco y sin conocimiento del mundo externo. 2. Una función no tiene efectos secundarios. Llamar a una función una vez es lo mismo que llamarla dos veces y descartar el resultado de la primera llamada.
- ^ Brian Lonsdorf (2015). "Guía mayoritariamente adecuada del profesor Frisby para la programación funcional" . GitHub . Consultado el 20 de marzo de 2020 .
Una función pura es una función que, dada la misma entrada, siempre devolverá la misma salida y no tiene ningún efecto secundario observable.
- ^ a b "Manual de GCC 8.1" . GCC, la colección de compiladores GNU . Free Software Foundation, Inc. 2018 . Consultado el 28 de junio de 2018 .
- ^ Funciones del lenguaje Fortran 95 # Procedimientos puros
- ^ Peyton Jones, Simon L. (2003). Haskell 98 Language and Libraries: The Revised Report (PDF) . Cambridge, Reino Unido: Cambridge University Press. pag. 95. ISBN 0-521 826144. Consultado el 17 de julio de 2014 .
- ^ Hanus, Michael. "Curry: un lenguaje lógico funcional integrado" (PDF) . www-ps.informatik.uni-kiel.de . Institut für Informatik, Christian-Albrechts-Universität zu Kiel. pag. 33. Archivado desde el original (PDF) el 25 de julio de 2014 . Consultado el 17 de julio de 2014 .
enlaces externos
- Atributo puro en Fortran
- atributo constexpr en C ++
- Atributo puro en lenguaje D