Dado que la pureza de un parámetro de entrada es desconocida hasta el tiempo de ejecución, ¿se considera una función inmediatamente impura si toma una función como parámetro de entrada?
Relacionado: si una función aplica una función pura que se define fuera de la función, pero no se pasa como parámetro, ¿sigue siendo pura si cumple los criterios de no tener efectos secundarios y la salida depende únicamente de la entrada?
Por contexto, estoy escribiendo código funcional en JavaScript.
functional-programming
pure-function
Dancrumb
fuente
fuente
foo = function(function bar){ print(bar.toString()) }
foo = function(function bar) { return 3; }
es puro y toma una función como argumento.toString()
(es decir, la que encontraría en el Objeto de Java).Respuestas:
Siempre que todos los valores utilizados en la función estén definidos únicamente por sus parámetros, es una función pura.
La faceta de que la salida es la misma cada vez para la misma entrada se controla si los parámetros son puros. Si asume que los parámetros (como un argumento de función) también son puros, entonces es puro.
En un lenguaje como Javascript donde la pureza no se aplica, esto significa que es posible hacer que una función pura tenga un comportamiento impuro invocando una función impura que se pasa como parámetro.
Esto significa efectivamente que para los lenguajes que no imponen la pureza (es decir, casi todos), es imposible definir una función pura que invoque funciones pasadas como argumentos. Todavía es útil escribirlos lo más puro posible y razonar sobre ellos como funciones puras, pero debe tener cuidado porque la suposición de que es pura se romperá si pasa los argumentos equivocados.
En mi experiencia en la práctica, esto no suele ser un gran problema: me resulta raro que las funciones impuras se utilicen como argumentos de función para funciones puras.
fuente
areaOfCircle r => Math.Pi * r * r
, ¿seráareaOfCircle
no pura ya que no solo usa parámetros?f(f2)
que invocaf2
no depende de forma transitiva de nada en lo que sef2
basa. Una función que podría invocar funciones arbitrarias pasadas no es pura.function compose(f, g) {return function h(x) {return f(g(x));};}
, que es puro a pesar de tomar las funciones como argumentos.find
rutina a un predicado impuro que devuelve "verdadero" para el tercer elemento coincidente que encuentra, o alguna tontería.No. Contraejemplo:
No importa si
other_function
es una función pura, una función impura o no es una función en absoluto. Lapure
función es pura.Otro contraejemplo:
Esta función es pura, incluso si
x
es una función impura.identity(impure_function)
siempre regresaráimpure_function
, sin importar cuántas veces repita la llamada. No importa siidentity(impure_function)()
siempre devuelve lo mismo; El valor de retorno de una función no afecta su pureza.En general, si una función puede llamar a una función, se pasó como argumento, no es pura. Por ejemplo, una función
function call(f) {f();}
no es pura, porque a pesar de que no menciona ningún estado global o mutable,f
podría ser algo asíalert
que cause efectos secundarios visibles.Si una función toma funciones como argumentos, pero no las llama ni hace que se llamen, entonces puede ser pura. Todavía podría ser impuro si hace alguna otra cosa impura. Por ejemplo,
function f(ignored_function) {alert('This isn't pure.');}
es impuro, aunque nunca llameignored_function
.fuente
Técnicamente, sí, a menos que haya alguna forma en su idioma para garantizar que la función de entrada también sea pura.
Si. Así que centrémonos en lo que importa aquí. Llamar a una función pura o no no es en sí misma útil. Las funciones puras son útiles porque producir el mismo resultado para cualquier entrada y no depender del estado o tener efectos secundarios es un conjunto de propiedades muy útil. Significa que una vez que se ha ejecutado su función, puede "recordar" la respuesta para esa entrada y siempre será verdadera. Tampoco necesita ejecutar la función nuevamente para generar efectos secundarios. Y puede ejecutar esa función en paralelo (o fuera de orden) con otras funciones y saber que no tendrán interacciones ocultas que se comporten mal.
Esas propiedades útiles aún se mantienen si la función usa otras funciones de solo lectura para hacer su trabajo, independientemente de cómo las haga referencia.
fuente
Como dijo Telastyn: Técnicamente, sí, a menos que haya alguna forma en su idioma para garantizar que la función de entrada también sea pura.
Eso no es hipotético, de hecho, hay buenas maneras de garantizar esto. Al menos en un lenguaje fuertemente tipado.
Una función ~ tan pura que escribirías en JavaScript como
se puede traducir directamente a Haskell:
Ahora, en JavaScript puedes hacer cosas malas como
Esto no es posible en Haskell . La razón es que algo como efectos secundarios
console.log()
siempre debe tener un tipo de resultadoIO something
, nosomething
solo.Para que esta expresión escriba typecheck, necesitaríamos dar
foo
la firma de tipoPero resulta que ya no puedo implementarlo más: porque la función de argumento tiene
IO
su resultado, no puedo usarlo dentrofoo
.La única forma en que podría usar una
IO
acciónfoo
es si el resultado defoo
tiene el tipo enIO Int
sí mismo:Pero en este punto, queda claro por la firma de
foo
que tampoco es una función pura.fuente
unsafeIO
:-)IO
. Por cierto, también se puede usar para causar caos al ocultar los efectos secundarios en una función "pura", pero eso es realmente inseguro en Haskell porque no hay una forma confiable de especificar el orden de evaluación de las funciones puras.unsafeIO
; esa es una escotilla de escape de último recurso que elude el sistema de tipos garantizado y, por lo tanto, el suyo no es un buen punto.No, no es.
Si la función aprobada es impura Y su función llama a la función aprobada, entonces su función se considerará impura.
La relación pura / impura es un poco como sync / async en JS. Puede usar libremente código puro de impuro, pero no al revés.
fuente