O seguinte é uma função pura?
function test(min,max) {
return Math.random() * (max - min) + min;
}
Meu entendimento é que uma função pura segue estas condições:
- Ele retorna um valor calculado a partir dos parâmetros
- Ele não faz nenhum trabalho além de calcular o valor de retorno
Se esta definição estiver correta, minha função é uma função pura? Ou meu entendimento do que define uma função pura está incorreto?
javascript
function
pure-function
Kiwi Rupela
fonte
fonte
Math.random()
que muda o estado do RNG.test(a,b)
sempre retorna o mesmo objetoRandom(a,b)
(que pode representar diferentes números concretos)? Se você mantiver oRandom
simbólico, ele é puro no sentido clássico, se você avaliá-lo cedo e colocar em números, talvez como uma espécie de otimização, a função ainda retém alguma "pureza".Respostas:
Não, não é. Dada a mesma entrada, esta função retornará valores diferentes. E então você não pode construir uma 'tabela' que mapeie a entrada e as saídas.
Do artigo da Wikipedia para a função Pure :
Além disso, outra coisa é que uma função pura pode ser substituída por uma tabela que representa o mapeamento da entrada e saída, conforme explicado neste tópico .
Se você quiser reescrever esta função e alterá-la para uma função pura, você deve passar o valor aleatório como um argumento também
e chame-o desta forma (por exemplo, com 2 e 5 como mínimo e máximo):
fonte
Math.random
?Math.random
produção futura ); para que seja puro, você teria que salvar de alguma forma o estado RNG atual, propagá-lo novamente, chamá-Math.random
lo e restaurá-lo ao estado anterior.A resposta simples para sua pergunta é que
Math.random()
viola a regra nº 2.Muitas outras respostas aqui indicaram que a presença de
Math.random()
significa que essa função não é pura. Mas acho que vale a pena dizer porMath.random()
que as funções de contaminação que o usam.Como todos os geradores de números pseudoaleatórios,
Math.random()
começa com um valor "semente". Em seguida, ele usa esse valor como ponto de partida para uma cadeia de manipulações de bits de baixo nível ou outras operações que resultam em uma saída imprevisível (mas não realmente aleatória ).Em JavaScript, o processo envolvido depende da implementação e, ao contrário de muitas outras linguagens, o JavaScript não fornece nenhuma maneira de selecionar a semente :
É por isso que essa função não é pura: JavaScript está essencialmente usando um parâmetro de função implícito sobre o qual você não tem controle. Ele está lendo esse parâmetro de dados calculados e armazenados em outro lugar e, portanto, viola a regra nº 2 em sua definição.
Se você quiser fazer disso uma função pura, poderá usar um dos geradores de números aleatórios alternativos descritos aqui . Chame aquele gerador
seedable_random
. Leva um parâmetro (a semente) e retorna um número "aleatório". Claro, esse número não é realmente aleatório; é determinado exclusivamente pela semente. É por isso que esta é uma função pura. A saída deseedable_random
é apenas "aleatória" no sentido de que é difícil prever a saída com base na entrada.A versão pura desta função precisaria de três parâmetros:
Para qualquer dado triplo de
(min, max, seed)
parâmetros, isso sempre retornará o mesmo resultado.Observe que, se você quiser que a saída de
seedable_random
seja realmente aleatória, precisará encontrar uma maneira de tornar a semente aleatória! E qualquer estratégia que você usasse seria inevitavelmente não pura, porque exigiria que você reunisse informações de uma fonte externa à sua função. Como o mtraceur e o jpmc26 me lembram, isso inclui todas as abordagens físicas: geradores de números aleatórios de hardware , webcams com tampas de lente , coletores de ruído atmosférico - até lâmpadas de lava . Tudo isso envolve o uso de dados calculados e armazenados fora da função.fonte
Math.random
você não usasse um PRNG, mas fosse implementado usando um RNG de hardware? O hardware RNG realmente não tem estado no sentido normal, mas ele produz valores aleatórios (e, portanto, a saída da função ainda é diferente, independentemente da entrada), certo?Uma função pura é uma função em que o valor de retorno é determinado apenas por seus valores de entrada, sem efeitos colaterais observáveis
Ao usar Math.random, você está determinando seu valor por algo diferente dos valores de entrada. Não é uma função pura.
fonte
fonte
Não, não é uma função pura porque sua saída não depende apenas da entrada fornecida (Math.random () pode produzir qualquer valor), enquanto as funções puras devem sempre produzir o mesmo valor para as mesmas entradas.
Se uma função for pura, é seguro otimizar várias chamadas com as mesmas entradas e apenas reutilizar o resultado de uma chamada anterior.
PS, pelo menos para mim e para muitos outros, redux tornou o termo função pura popular. Direto dos documentos redux :
fonte
Do ponto de vista matemático, sua assinatura não é
mas
onde o
environment
é capaz de fornecer resultadosMath.random()
. E, de fato, gerar o valor aleatório altera o ambiente como um efeito colateral, então você também retorna um novo ambiente, que não é igual ao primeiro!Em outras palavras, se você precisa de qualquer tipo de entrada que não venha dos argumentos iniciais (a
<number, number>
parte), então você precisa de um ambiente de execução (que neste exemplo fornece estado paraMath
). O mesmo se aplica a outras coisas mencionadas por outras respostas, como I / O ou algo semelhante.Como uma analogia, você também pode notar que é assim que a programação orientada a objetos pode ser representada - se dissermos, por exemplo
então, na verdade, estamos usando
com o objeto que tem seu método invocado sendo parte do ambiente. E por que a
SomeClass
parte do resultado? Porquesomething
o estado de também poderia ter mudado!fonte
test: <environment, number, number> -> <environment, number>
deveria estara.F(b, c)
pode ser visto como um açúcar sintático paraF(a, b, c)
com uma regra especial para despachar para definições sobrecarregadas de comF
base no tipo dea
(na verdade é assim que Python o representa). Masa
ainda é explícito em ambas as notações, enquanto o ambiente em uma função não pura nunca é mencionado no código-fonte.Funções puras sempre retornam o mesmo valor para a mesma entrada. As funções puras são previsíveis e transparentes quanto ao referencial, o que significa que podemos substituir a chamada da função pela saída retornada e isso não mudará o funcionamento do programa.
https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md
fonte
Além das outras respostas que apontam corretamente como essa função é não determinística, ela também tem um efeito colateral: fará com que chamadas futuras
math.random()
para retornem uma resposta diferente. E um gerador de números aleatórios que não tem essa propriedade geralmente executa algum tipo de E / S, como ler de um dispositivo aleatório fornecido pelo sistema operacional. Qualquer um é proibido para uma função pura.fonte
Não, não é. Você não consegue descobrir o resultado de forma alguma, portanto, esse pedaço de código não pode ser testado. Para tornar esse código testável, você precisa extrair o componente que gera o número aleatório:
Agora, você pode simular o gerador e testar seu código corretamente:
E em seu código de "produção":
fonte
util.Random
, que pode ser propagado no início de uma execução de teste para repetir o comportamento antigo ou para uma nova (mas repetível) execução. Se for multi-threading, você poderá fazer isso no thread principal e usá-loRandom
para semear threads locais repetíveisRandom
. No entanto, pelo que entendi,test(int,int,Random)
não é considerado puro, pois altera o estado doRandom
.Você estaria bem com o seguinte:
ser equivalente a
?
Veja, a definição de puro é uma função cuja saída não muda com nada além de suas entradas. Se dissermos que o JavaScript tem uma maneira de marcar uma função pura e tirar vantagem disso, o otimizador terá permissão para reescrever a primeira expressão como a segunda.
Tenho experiência prática com isso. Servidor SQL permitido
getdate()
enewid()
em funções "puras" e o otimizador eliminaria as chamadas à vontade. Às vezes, isso faria algo estúpido.fonte