language agnostic - Pureza vs transparencia referencial
language-agnostic functional-programming (5)
Los términos parecen definirse de manera diferente, pero siempre he pensado que uno implicaba al otro; No puedo pensar en ningún caso cuando una expresión sea referencialmente transparente pero no pura, o viceversa.
Wikipedia mantiene artículos separados para estos conceptos y dice:
De la transparencia referencial :
Si todas las funciones involucradas en la expresión son funciones puras, entonces la expresión es referencialmente transparente. Además, algunas funciones impuras se pueden incluir en la expresión si sus valores se descartan y sus efectos secundarios son insignificantes.
De las expresiones puras :
Se requieren funciones puras para construir expresiones puras. [...] Las expresiones puras a menudo se conocen como referencialmente transparentes.
Encuentro estas declaraciones confusas. Si los efectos secundarios de una llamada "función impura" son lo suficientemente insignificantes para permitir que no se realicen (es decir, reemplazar una llamada a esa función con su valor ) sin cambiar materialmente el programa, es lo mismo que si fuera puro Primer lugar, ¿no es así?
¿Existe una forma más sencilla de entender las diferencias entre una expresión pura y una referencia transparente, si la hay? Si hay una diferencia, se agradecería una expresión de ejemplo que demuestre claramente que es así.
Citaré lo que escribió John Mitchell en su libro Concept en lenguaje de programación . No lo recuerdo línea por línea, pero él define que el lenguaje funcional puro tiene que pasar el examen de lenguaje declarativo que es:
"Dentro del alcance de la desaceleración específica de x1, ..., xn, toda la aparición de una expresión e que contiene solo las variables x1, ..., xn tiene el mismo valor".
En resumen, como todos los demás mencionaron sin efectos secundarios o sin efectos secundarios ("Falta" de efectos secundarios).
En lingüística, un nombre o frase nominal se considera transparente referencialmente si puede reemplazarse por otra frase nominal con el mismo referente sin cambiar el significado de la oración que contiene.
Lo que en el primer caso es válido pero en el segundo es demasiado extraño.
Caso 1: "Vi a Walter entrar en su nuevo auto ".
Y si Walter posee un Centro, podríamos reemplazarlo en la oración dada como:
"Vi a Walter entrar en su Centro "
Al contrario de lo primero:
Caso # 2: Se llamaba William Rufus debido a su barba leída.
Rufo significa algo rojo y la referencia fue a Guillermo IV de Inglaterra.
"Se llamaba Guillermo IV por su barba leída". se ve muy incomodo
La manera tradicional de decir es que un lenguaje es referencialmente transparente si podemos reemplazar una expresión con otra de igual valor en cualquier parte del programa sin cambiar el significado del programa.
Entonces, la transparencia referencial es una propiedad del lenguaje funcional puro. Y si su programa está libre de efectos secundarios, esta propiedad se mantendrá.
Así que renunciar a él es un consejo increíble, pero ponerlo en él también podría verse bien en este contexto.
No estoy seguro de la respuesta que ofrezco aquí, pero seguramente alguien nos indicará en alguna dirección. :-)
En general, se considera que "pureza" significa "falta de efectos secundarios". Se dice que una expresión es pura si su evaluación carece de efectos secundarios. ¿Qué es un efecto secundario entonces? En un lenguaje puramente funcional, el efecto secundario es cualquier cosa que no se cumpla con la regla beta simple (la regla que para evaluar la aplicación de la función es la misma que para sustituir el parámetro real por todas las apariciones libres del parámetro formal).
Por ejemplo, en un lenguaje funcional con tipos lineales (o exclusividad, esta distinción no debería molestar en este momento) se permite alguna mutación (controlada).
Así que supongo que hemos resuelto qué "pureza" y "efectos secundarios" podrían ser.
La transparencia referencial (de acuerdo con el artículo de Wikipedia que citó) significa que la variable puede ser reemplazada por la expresión que denota (abreviada, significa) sin cambiar el significado del programa en cuestión (por cierto, esta es también una pregunta difícil de abordar, y No intentaré hacerlo aquí. Por lo tanto, "pureza" y "transparencia referencial" son, de hecho, cosas diferentes: "pureza" es una propiedad de alguna expresión, más o menos significa "no produce efectos secundarios cuando se ejecuta", mientras que "transparencia referencial" es una propiedad que relaciona variables y expresiones que significa "variable puede ser reemplazada por lo que denota".
Esperemos que esto ayude.
Si reúno en un solo lugar a tres teóricos de mi relación, al menos dos de ellos no están de acuerdo sobre el significado del término "transparencia referencial". Y cuando era un estudiante joven, un mentor mío me entregó un documento en el que explicaba que incluso si consideras solo la literatura profesional, la frase "referencialmente transparente" se usa para significar al menos tres cosas diferentes. (Desafortunadamente, ese papel está en algún lugar de una caja de reimpresiones que aún no se han escaneado. Busqué en Google Scholar pero no tuve éxito).
No puedo informarle, pero puedo aconsejarle que se dé por vencido: dado que incluso el pequeño grupo de teóricos del lenguaje de cabeza puntiaguda no puede ponerse de acuerdo sobre lo que significa, el término "referencialmente transparente" no es útil . Así que no lo uses.
PD: En cualquier tema relacionado con la semántica de los lenguajes de programación, Wikipedia no es confiable. He dejado de intentar arreglarlo; El proceso de Wikipedian parece considerar el cambio y la votación popular sobre la estabilidad y la precisión.
Todas las funciones puras son necesariamente referencialmente transparentes. Como, por definición, no pueden acceder a nada más que a lo que se les pasa, su resultado debe estar completamente determinado por sus argumentos.
Sin embargo, es posible tener funciones referencialmente transparentes que no son puras. Puedo escribir una función a la que se le asigna un int i
, luego genera un número aleatorio r
, resta r
de sí mismo y la coloca en s
, luego devuelve i - s
. Claramente esta función es impura, porque está generando números aleatorios. Sin embargo, es referencialmente transparente. En este caso, el ejemplo es tonto y artificial. Sin embargo, en, por ejemplo, Haskell, la función id
es de tipo a - > a
mientras que mi función stupidId
sería de tipo a -> IO a
lo que indica que hace uso de efectos secundarios. Cuando un programador puede garantizar a través de una prueba externa que su función es referencialmente transparente, entonces pueden usar unsafePerformIO
para quitar el IO
del tipo.
Estas diapositivas de una charla de ACCU2015 tienen un gran resumen sobre el tema de la transparencia referencial.
De una de las diapositivas:
Un lenguaje es referencialmente transparente si (a) cada subexpresión puede ser reemplazada por cualquier otra que sea igual en valor y (b) todas las apariciones de una expresión dentro de un contexto dado producen el mismo valor.
Puede tener, por ejemplo, una función que registra su cálculo en la salida estándar del programa (por lo tanto, no será una función pura), pero puede reemplazar las llamadas para esta función por una función similar que no registra su cálculo . Por lo tanto, esta función tiene la propiedad de transparencia referencial . Pero ... la definición anterior se refiere a los idiomas, no a las expresiones, como se destaca en las diapositivas.
[...] es lo mismo que si fuera puro en primer lugar, ¿no es así?
De las definiciones que tenemos, no, no lo es.
¿Existe una forma más sencilla de entender las diferencias entre una expresión pura y una referencia transparente, si la hay?