Como a pureza de um parâmetro de entrada é desconhecida até o tempo de execução, uma função é imediatamente considerada impura se ela assume uma função como parâmetro de entrada?
Relacionado: se uma função aplica uma função pura que é definida fora da função, mas não é passada como parâmetro, ela ainda é pura se atender aos critérios de não ter efeitos colaterais e a saída depender apenas da entrada?
Por contexto, estou escrevendo código funcional em JavaScript.
functional-programming
pure-function
Dancrumb
fonte
fonte
foo = function(function bar){ print(bar.toString()) }
foo = function(function bar) { return 3; }
é puro e assume uma função como argumento.toString()
(ou seja, o que você encontraria no objeto Java).Respostas:
Desde que todos os valores usados na função sejam definidos apenas por seus parâmetros, é uma função pura.
A faceta em que a saída é sempre a mesma para a mesma entrada é controlada se os parâmetros são puros. Se você assumir que os parâmetros (como um argumento de função) também são puros, então é puro.
Em uma linguagem como Javascript, onde a pureza não é imposta, isso significa que é possível fazer com que uma função pura seja de outro modo impura, invocando uma função impura passada como parâmetro.
Isso significa efetivamente que, para linguagens que não impõem pureza (ou seja, quase todas), é impossível definir uma função pura que invoque funções passadas como argumentos. Ainda é útil escrevê-los o mais puro possível e argumentar sobre eles como funções puras, mas é preciso ter cuidado, pois a suposição de que é puro será quebrada se você passar os argumentos errados.
Na minha experiência na prática, isso geralmente não é grande coisa - acho raro que funções impuras sejam usadas como argumentos de função para funções puras.
fonte
areaOfCircle r => Math.Pi * r * r
, seráareaOfCircle
não pura, pois não usa apenas parâmetros?f(f2)
que invocaf2
não depende transitivamente de algo em que sef2
baseia. Uma função que pode invocar funções passadas arbitrárias não é pura.function compose(f, g) {return function h(x) {return f(g(x));};}
, o que é puro, apesar de ter funções como argumentos.find
rotina um predicado impuro que retorne "true" para o terceiro item correspondente que encontrar, ou algo parecido.Não. Contra-exemplo:
Não importa se
other_function
é uma função pura, uma função impura ou não uma função. Apure
função é pura.Outro contra-exemplo:
Esta função é pura, mesmo que
x
seja uma função impura.identity(impure_function)
sempre retornaráimpure_function
, não importa quantas vezes você repita a chamada. Não importa seidentity(impure_function)()
sempre retorna a mesma coisa; o valor de retorno de uma função não afeta sua pureza.Em geral, se uma função pode chamar uma função que foi passada como argumento, não é pura. Por exemplo, uma função
function call(f) {f();}
não é pura, porque, embora não faça menção a nenhum estado global ou mutável,f
pode ser algo assimalert
que causa efeitos colaterais visíveis.Se uma função aceita funções como argumentos, mas não as chama ou faz com que sejam chamadas, pode ser pura. Ainda pode ser impuro se fizer alguma outra coisa impura. Por exemplo,
function f(ignored_function) {alert('This isn't pure.');}
é impuro, mesmo que nunca ligueignored_function
.fonte
Tecnicamente, sim, a menos que haja alguma maneira no seu idioma para garantir que a função de entrada também seja pura.
Sim. Então, vamos nos concentrar no que importa aqui. Chamar uma função pura ou não não é, por si só, útil. As funções puras são úteis porque produzir a mesma saída para qualquer entrada e não depender do estado ou causar efeitos colaterais é um conjunto de propriedades muito útil. Isso significa que, uma vez executada sua função, você pode "lembrar" a resposta para essa entrada e ela sempre será verdadeira. Você também não precisa executar a função novamente para gerar efeitos colaterais. E você pode executar essa função em paralelo (ou fora de ordem) com outras funções e saber que elas não terão nenhuma interação oculta que se comporte mal.
Essas propriedades úteis ainda são válidas se a função usar outras funções somente leitura puras para executar seu trabalho, independentemente de como as referencie.
fonte
Como Telastyn disse: Tecnicamente, sim, a menos que haja alguma maneira no seu idioma para garantir que a função de entrada também seja pura.
Isso não é hipotético, existem realmente boas maneiras de garantir isso. Pelo menos em uma linguagem fortemente tipada.
Uma função ~ tão pura que você escreveria em JavaScript como
pode ser traduzido diretamente para Haskell:
Agora, em JavaScript, você pode fazer coisas más, como
Isso não é possível em Haskell . A razão é que algo como efeito colateral
console.log()
deve sempre ter um tipo de resultadoIO something
, não apenassomething
sozinho.Para essa expressão digitar, precisaríamos dar
foo
a assinatura de tipoMas acontece que não posso mais implementá-lo: como a função argumento tem
IO
como resultado, não posso usá-la dentrofoo
.A única maneira pela qual eu poderia usar uma
IO
açãofoo
é se o resultado defoo
tiver oIO Int
próprio tipo :Mas, neste momento, fica claro pela assinatura
foo
que também não é uma função pura.fonte
unsafeIO
:-)IO
. Aliás, também pode ser usado para causar confusão, ocultando efeitos colaterais em uma função "pura", mas isso é realmente inseguro em Haskell, porque não há realmente uma maneira confiável de especificar a ordem de avaliação das funções puras.unsafeIO
; é uma escotilha de escape de último recurso que contorna as garantias do sistema de tipos e, portanto, o seu não é um bom ponto.Não não é.
Se a função passada for impura E sua função chamar a função passada, sua função será considerada impura.
A relação pura / impura é um pouco como sync / async em JS. Você pode usar livremente código puro de impuro, mas não o contrário.
fonte