Según Wikipedia:
En la programación de computadoras, una función puede describirse como pura si ambas afirmaciones sobre la función se mantienen: la función siempre evalúa el mismo valor de resultado dados los mismos valores de argumento. El valor del resultado de la función no puede depender de ninguna información oculta o estado que pueda cambiar a medida que avanza la ejecución del programa o entre diferentes ejecuciones del programa, ni puede depender de ninguna entrada externa de los dispositivos de E / S. La evaluación del resultado no causa ningún efecto secundario o salida semánticamente observable, como la mutación de objetos mutables o la salida a dispositivos de E / S.
Me pregunto si es posible escribir una función que calcule si una función es pura o no. Código de ejemplo en Javascript:
function sum(a,b) {
return a+b;
}
function say(x){
console.log(x);
}
isPure(sum) // True
isPure(say) // False
if (rand(1000000)<2) return WRONG_ANSWER
, probar la función muchas veces para obtener un comportamiento consistente no ayudará. Pero, si tiene acceso a la definición de la función, la prueba es trivial.say
llamadasconsole.log
que son impuras tambiénsay
son impuras.Respuestas:
Sí, es posible, dependiendo del idioma.
En JavaScript, puede saber si una función es pura con los siguientes criterios:
Solo lee parámetros y locales;
Solo escribe locales;
En no locales, solo llama a funciones puras;
Todas las funciones que llama implícitamente son puras, por ejemplo
toString
; ySolo escribe propiedades de locales si no alias no locales.
El aliasing no es posible determinar en JavaScript en el caso general, porque siempre puede buscar propiedades de un objeto dinámicamente (
object["property"]
). Siempre que nunca haga eso, y tenga la fuente de todo el programa, entonces creo que el problema es manejable. También necesitaría información sobre qué funciones nativas tienen efectos secundarios, comoconsole.log
o casi cualquier cosa que involucre al DOM.El término "puro" también podría usar alguna aclaración. Incluso en un lenguaje de programación puramente funcional, fuertemente tipado y estático, donde todas las funciones son referencialmente transparentes, una función puede fallar al finalizar. Entonces, cuando hablamos
id :: a -> a
, lo que realmente estamos diciendo no es:Pero más bien:
Porque una implementación válida de
id
eserror "Not implemented!"
. Como Peteris señala, esta no totalidad podría verse como una especie de impureza. Koka es un lenguaje de programación funcional, con una sintaxis modelada en JavaScript, que puede inferir posibles efectos como divergencia (no terminación), transparencia referencial, lanzamiento de excepciones y acciones de E / S.fuente
toString
es puro para cualquier objeto que use como cadena.function a (o) { return o.method(); }
- en realidad no podemos responder esto, porque depende de qué parámetroo
se pase. Además, no podemos dar cuenta de lo que sucede si una función pura previamente certificada se cambia a una implementación no pura, que siempre es un problema potencial con JavaScript.No. Puede verificar fácilmente si una función solo realiza operaciones "puramente seguras", como se describe en la respuesta de Jon Purdy, pero eso es IMO que no es suficiente para responder la pregunta.
Considere esta función:
Obviamente, si
someCheck
es impuro, también lo espossiblyPure
. Pero, sisomeCheck
es puro y devuelvetrue
todos los valores posibles dex
,possiblyPure
es puro, ¡ya que la ruta del código no es inalcanzable!Y aquí viene la parte difícil: determinar si
someCheck
devuelve verdadero o no para cada entrada posible. Intentar responder a esa pregunta inmediatamente te lleva al reino del problema de detención y problemas similares indecidibles.EDITAR: prueba de que es imposible
Existe cierta incertidumbre sobre si una función pura debe terminar en cada entrada posible o no. Pero en ambos casos, el problema de detención puede usarse para mostrar que la verificación de pureza es imposible.
Caso A) Si se requiere una pura función de interrumpir en cada entrada posible, se tiene que resolver el problema de la parada para determinar si es o no la función es puro. Como se sabe que esto es imposible, según esta definición, la pureza no puede calcularse.
Caso B) Si se permite que una función pura no termine en algunas entradas, podemos construir algo así: supongamos que
isPure(f)
calcula sif
es una cadena que define una función pura.Ahora
isPure
tiene que determinar si sef
detiene o no en su propia fuente como entrada. Si se detiene,upf
es impuro; si no termina,upf
es puro ifff
es puro.Si
isPure
funcionó como se esperaba (devuelve resultados correctos y termina en cada entrada), ¡habríamos resuelto el problema de detención (*)! Como se sabe que esto es imposible,isPure
no puede existir.(*) para funciones de JavaScript puro, que es suficiente para resolverlo también en la máquina de turing.
fuente
Esta pregunta de stackoverflow tiene una respuesta de yfeldblum que es relevante aquí. (Y tiene un voto negativo por alguna razón que no puedo entender. ¿Sería una mala etiqueta votar a favor de algo que tiene 3 años?) Él da una prueba de que si una función es pura es reducible al problema de detención en un comentario.
Creo que desde un punto de vista práctico no sería demasiado difícil para algunos idiomas si dejas que la función devuelva sí, no o tal vez. Estaba viendo un video sobre Clojure hace un par de días, y el orador había hecho un recuento de casos de impureza en una base de código buscando alrededor de 4 cadenas diferentes (como "ref"). Debido al énfasis de Clojure en la pureza y la segregación de las cosas impuras, fue trivial, pero no era exactamente lo que estaba buscando.
Entonces, teóricamente imposible, prácticamente posible si modifica un poco la pregunta, y creo que lo difícil que sería dependería en gran medida del idioma. Lenguajes más simples / limpios con un enfoque en la inmutabilidad y una buena reflexión sería más fácil.
fuente
bottom
es un valor válido de primera clase, no merece ser discriminado de esta manera.Gran pregunta
Lo mejor que puede hacer en la práctica, suponiendo que no tenga la capacidad de escuchar acciones de E / S para llamar a la función tantas veces como sea posible. Luego vea si el valor de retorno es consistente.
Pero no puedes hacer esto en general. Podría decirse que los programas que no se detienen no son puros, y no podemos decidir el problema de detención.
fuente
void
función sería "pura", lo cual es claramente falso.No es posible en el caso general. Ver problema de detención . Brevemente, es imposible escribir un programa que, dada una función arbitraria y una entrada, determina si el programa se detendrá o se ejecutará para siempre. Si se ejecuta para siempre, no es una función pura que se ajuste a la definición que dio.
fuente
bottom
valor.