Por que o Today () é um exemplo de uma função impura?

38

Parece que, ao ler algo como este artigo da Wikipédia sobre "funções puras" , eles listam Today() como um exemplo de uma função impura, mas parece muito pura para mim. É porque não há argumento de entrada formal? Por que a hora do dia não é tratada como "entrada para a função", nesse caso, se você deu a mesma entrada, isto é, executou today() duas vezes ao mesmo tempo, ou viajou de volta no tempo para executá-la novamente? uma hipotética :)), a saída seria o mesmo tempo. Today() nunca te dá um número aleatório. sempre te dá a hora do dia.

O artigo da Wikipedia diz "tempos diferentes resultará em resultados diferentes", mas isso é como dizer que para diferentes x sin(x) você terá diferentes proporções. E sin(x) é o exemplo de uma função pura.

    
por Brad 23.01.2013 / 16:22
fonte

10 respostas

103

Is it because there is no formal input argument?

É porque a saída depende de algo que não é uma entrada, ou seja, a hora atual.

Why is the actual time of day not treated as the "input to the function"

Porque você não passou isso como um parâmetro. Se você o passou como um parâmetro, a função se tornaria uma função de identidade em datas, o que é bastante inútil. O ponto inteiro de uma função Today() é produzir algo que depende de um valor externo e em constante mudança (tempo).

A vantagem das funções puras é que seu comportamento é absolutamente reprodutível e determinístico, facilitando a obtenção de provas formais e garantias rígidas. Eles sempre fazem a mesma coisa. Today() é praticamente o oposto: sempre (permitindo granularidade de tempo) faz algo diferente.

    
por 23.01.2013 / 16:30
fonte
24

sin(x) sempre retornará o mesmo valor, contanto que x permaneça o mesmo. Today() poderia retornar resultados diferentes ao longo do tempo porque depende de valores fora do seu controle . Por exemplo, se algo além do controle de seu programa alterar o $current_datetime do sistema enquanto seu programa estiver sendo executado, Today() produzirá resultados diferentes de repente.

    
por 23.01.2013 / 16:23
fonte
13

Hoje () é uma função impura porque seu resultado depende de algo que você não dá; especificamente, a hora atual do sistema. Portanto, seu resultado não é determinístico quando baseado apenas nas entradas fornecidas na invocação.

Uma função pura seria int Add(int a, int b) {return a + b;} . A função trabalha somente com o que é dado e não usa nenhum outro dado de estado externo. O resultado natural disso é que você pode Add(2,2) e obter 4 a partir de agora até o final do tempo. Além disso, como a função não altera nenhum estado externo (não tem "efeitos colaterais"), Add () 2 e 2 a partir de agora até o final do tempo não alterará mais nada no sistema, a menos que você atribua o resultado da função a uma variável ou use o valor para atualizar o estado (que não é uma operação executada pela própria função). Praticamente todas as operações matemáticas clássicas são funções puras e podem ser implementadas como tal.

Hoje (), por outro lado, pode produzir o mesmo valor quando chamado duas vezes seguidas, mas não se for chamado repetidamente por vários dias. Isso ocorre porque depende de dados de estado externos que não são fornecidos por você como um parâmetro para a função. Como resultado, é impossível, dentro dos limites do programa, controlar o resultado da função Today (). Ele produzirá um determinado valor em um determinado dia e nunca produzirá esse valor em outro dia, a menos que você altere o relógio do sistema no qual ele é executado (uma alteração geralmente ocorrendo fora dos limites do programa). / p>

Uma função impura não é necessariamente uma coisa ruim; funções impuras são necessárias, mesmo em linguagens funcionais, para interagir com qualquer coisa fora dos limites do programa, como armazenamentos de dados, pipelines de comunicação, exibições de interface do usuário, dispositivos periféricos etc. Um programa que não faz nada disso é um programa isto é agudamente limitado em sua utilidade; Eu chegaria a ponto de chamar esse programa de trivialidade, pois, sem meios para aceitar contribuições ou qualquer meio de informá-lo de sua produção, poderia muito bem não estar fazendo nada. Programas escritos em linguagens funcionais podem ter apenas a entrada fornecida pelo tempo de execução e produzir uma saída reportada ao tempo de execução sem qualquer método impuro explicitamente definido, mas isso porque o tempo de execução está abstraindo todos esses detalhes impuros de trabalhar dentro de um sistema de computador imperfeito. que o próprio programa pode ser estruturado em termos de um conjunto aninhado de expressões matemáticas que o tempo de execução avalia, então, a entrada inicial dada.

É simplesmente uma Coisa Muito Boa saber quais das funções que você está usando são puras e quais não são, para que você possa tomar boas decisões sobre como elas são usadas. Funções impuras, porque fazem coisas ou são dependentes de coisas que não são aparentes em seu uso, podem se comportar de forma imprevisível, dado apenas o conhecimento do uso. Mais conhecimento do propósito da função e, portanto, do que ela precisa ou não do estado externo, é necessário para colocar um sistema que a utiliza em um estado consistente e, assim, esperar um resultado determinístico.

    
por 23.01.2013 / 18:13
fonte
8

Parece bastante óbvio que esta função falha no primeiro teste de pureza dado no início da página:

  1. The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change as program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.

Note que, uma vez que não recebe argumentos, existe apenas um conjunto possível de valores de argumentos - o conjunto vazio. E esta função pode e retorna resultados diferentes para o (s) valor (es) do argumento mesmo '.

Além disso, o valor do resultado da função depende do "estado oculto ... que pode mudar conforme a execução do programa continua". Então, outro fracasso.

    
por 23.01.2013 / 16:39
fonte
8

() => 1 seria uma função pura, uma vez que sempre retorna 1. Today() pode retornar "segunda-feira" ou "terça-feira" ou quase qualquer outro valor.

Outra maneira de pensar nisso é que funções puras não dependem do estado. O mundo é tipicamente considerado estado. Você precisa conhecer o estado da realidade para saber que dia é hoje.

No entanto, você não precisa saber nada de especial sobre o estado do mundo para saber o que é sin(x) . E sempre chamar para sin(x) para um determinado x retornará o mesmo valor.

    
por 23.01.2013 / 16:26
fonte
2

Date(timestamp) seria uma função pura. Por causa de sua idempotência. E porque não haveria efeito colateral.

Today() pode variar seu resultado dependendo de quando você o chama. Isso é o que torna impuro. Não é idempotente. Não tem efeito colateral, mas isso não o torna puro.

    
por 23.01.2013 / 16:27
fonte
2

Aqui está um pequeno pseudo código que eu penso quando se fala de funções puras

newValue = Function();
while(true)
{
   oldValue = newValue;
   newValue = Function();
   assert( newValue == oldValue );
}

Se isso for executado indefinidamente e nunca for possível disparar a declaração, é uma função pura. Mais ainda, se você tem uma função que usa args, então uma pequena modificação ...

oldValue = Function( importantVariableToYourApp );
newValue = Function( importantVariableToYourApp );
assert( newValue == oldValue );

Se você puder usar isso após cada atribuição de variável no seu aplicativo, e isso não alterar os resultados no seu aplicativo, e isso nunca falhará na declaração, então é uma função pura.

    
por 23.01.2013 / 21:00
fonte
2

Primeiro, não existe uma função sem argumento (ou uma matriz sem índices ou um mapa sem chaves). É a característica definidora de uma função mapear um ou mais valores de argumento para outro valor.

Portanto, today não é uma função, portanto, nenhuma função pura. Ou podemos interpretar a sintaxe

today()

um pouco para que isso signifique

today   ()      -- today, applied to the value ()

Em Haskell, por exemplo, isso seria válido:

data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving Show
today :: () -> Day
today () = ....?
main = print (today())

porque existe um type () com um único valor ().

A questão é apenas, como today pode calcular o dia da semana, se tiver apenas ()? Simplesmente não é possível sem ler o temporizador do sistema, diretamente ou através de funções impuras auxiliares.

O temporizador do sistema é um excelente exemplo para o estado global.

    
por 24.01.2013 / 22:14
fonte
1

O problema com today() é que ele pode gerar um resultado diferente se chamado duas ou mais vezes em uma função.

Aqui está um exemplo de código que poderia introduzir um bug.

function doSomething(when)
{
     if(today() == when)
     {
           // open a resource or create a temp file.....
     }

     // do some other work

     if(today() == when)
     {
           // close the resource or delete temp file.....
     }
}

É possível no exemplo acima. Que a segunda instrução if não será executada. Mesmo que o primeiro tenha feito. Deixando um recurso em um estado ruim.

    
por 24.01.2013 / 22:56
fonte
1

Para ser uma função pura, fornecer os mesmos parâmetros deve dar sempre o mesmo resultado.

Cada vez que chamamos Today() , estamos fornecendo os mesmos parâmetros (nenhum) e, ainda assim, não obtendo necessariamente o mesmo resultado (segunda, terça, etc).

    
por 03.02.2015 / 12:20
fonte