Est-ce que ce qui suit est une fonction pure?
function test(min,max) {
return Math.random() * (max - min) + min;
}
Ma compréhension est qu'une fonction pure suit ces conditions:
- Il renvoie une valeur calculée à partir des paramètres
- Il ne fait aucun travail autre que le calcul de la valeur de retour
Si cette définition est correcte, ma fonction est-elle une fonction pure? Ou est-ce que ma compréhension de ce qui définit une fonction pure est incorrecte?
javascript
function
pure-function
Kiwi Rupela
la source
la source
Math.random()
ce qui change l'état du RNG.test(a,b)
renvoie toujours le même objetRandom(a,b)
(qui peut représenter différents nombres concrets)? Si vous gardezRandom
symbolique, il est pur au sens classique, si vous l'évaluez tôt et le mettez en chiffres, peut-être comme une sorte d'optimisation, la fonction conserve encore une certaine «pureté».Réponses:
Non ce n'est pas. Étant donné la même entrée, cette fonction renverra des valeurs différentes. Et puis vous ne pouvez pas construire une «table» qui mappe l'entrée et les sorties.
Extrait de l'article Wikipedia sur la fonction Pure :
De plus, une autre chose est qu'une fonction pure peut être remplacée par une table qui représente le mappage de l'entrée et de la sortie, comme expliqué dans ce thread .
Si vous voulez réécrire cette fonction et la changer en une fonction pure, vous devez également passer la valeur aléatoire comme argument
puis appelez-le de cette façon (exemple, avec 2 et 5 comme min et max):
la source
Math.random
?Math.random
sortie future ); pour qu'il soit pur, vous devez en quelque sorte enregistrer l'état RNG actuel, le réamorcer, l'appelerMath.random
et le restaurer à l'état précédent.La réponse simple à votre question est que cela
Math.random()
enfreint la règle n ° 2.Beaucoup d'autres réponses ici ont souligné que la présence de
Math.random()
signifie que cette fonction n'est pas pure. Mais je pense que cela vaut la peine de dire pourquoiMath.random()
ternit les fonctions qui l'utilisent.Comme tous les générateurs de nombres pseudo-aléatoires,
Math.random()
commence par une valeur «de départ». Il utilise ensuite cette valeur comme point de départ pour une chaîne de manipulations de bits de bas niveau ou d'autres opérations qui aboutissent à une sortie imprévisible (mais pas vraiment aléatoire ).En JavaScript, le processus impliqué dépend de l'implémentation et, contrairement à de nombreux autres langages, JavaScript ne permet pas de sélectionner la graine :
C'est pourquoi cette fonction n'est pas pure: JavaScript utilise essentiellement un paramètre de fonction implicite sur lequel vous n'avez aucun contrôle. Il lit ce paramètre à partir de données calculées et stockées ailleurs, et enfreint donc la règle n ° 2 de votre définition.
Si vous souhaitez en faire une fonction pure, vous pouvez utiliser l'un des générateurs de nombres aléatoires alternatifs décrits ici . Appelez ce générateur
seedable_random
. Il prend un paramètre (la graine) et renvoie un nombre "aléatoire". Bien sûr, ce nombre n'est pas du tout aléatoire; il est uniquement déterminé par la graine. C'est pourquoi c'est une fonction pure. La sortie deseedable_random
est uniquement "aléatoire" dans le sens où la prédiction de la sortie basée sur l'entrée est difficile.La version pure de cette fonction aurait besoin de prendre trois paramètres:
Pour tout triple de
(min, max, seed)
paramètres donné, cela retournera toujours le même résultat.Notez que si vous voulez que la sortie de
seedable_random
soit vraiment aléatoire, vous devez trouver un moyen de randomiser la graine! Et quelle que soit la stratégie que vous utilisiez serait inévitablement non pure, car elle vous obligerait à collecter des informations auprès d'une source extérieure à votre fonction. Comme mtraceur et jpmc26 me le rappellent, cela inclut toutes les approches physiques: générateurs de nombres aléatoires matériels , webcams avec bouchons d'objectif , collecteurs de bruit atmosphérique - même lampes à lave . Tous ces éléments impliquent l'utilisation de données calculées et stockées en dehors de la fonction.la source
Math.random
n'utilisiez pas de PRNG mais était plutôt implémentée à l'aide d'un RNG matériel? Le RNG matériel n'a pas vraiment d'état au sens normal du terme, mais il produit des valeurs aléatoires (et donc la sortie de fonction est toujours différente quelle que soit l'entrée), non?Une fonction pure est une fonction où la valeur de retour n'est déterminée que par ses valeurs d'entrée, sans effets secondaires observables
En utilisant Math.random, vous déterminez sa valeur par autre chose que des valeurs d'entrée. Ce n'est pas une fonction pure.
la source
la source
Non, ce n'est pas une fonction pure car sa sortie ne dépend pas uniquement de l'entrée fournie (Math.random () peut générer n'importe quelle valeur), alors que les fonctions pures devraient toujours afficher la même valeur pour les mêmes entrées.
Si une fonction est pure, il est prudent d'optimiser plusieurs appels avec les mêmes entrées et de simplement réutiliser le résultat d'un appel précédent.
PS pour moi au moins et pour beaucoup d'autres, redux a rendu populaire le terme fonction pure . Directement à partir de la documentation redux :
la source
Du point de vue mathématique, votre signature n'est pas
mais
où le
environment
est capable de fournir des résultatsMath.random()
. Et la génération de la valeur aléatoire entraîne une mutation de l'environnement en tant qu'effet secondaire, de sorte que vous retournez également un nouvel environnement, qui n'est pas égal au premier!En d'autres termes, si vous avez besoin d'un type d'entrée qui ne provient pas des arguments initiaux (la
<number, number>
partie), vous devez disposer d'un environnement d'exécution (qui dans cet exemple fournit un étatMath
). La même chose s'applique à d'autres choses mentionnées par d'autres réponses, comme les E / S ou autres.Par analogie, vous pouvez également remarquer que c'est ainsi que la programmation orientée objet peut être représentée - si nous disons, par exemple
alors en fait nous utilisons
avec l'objet dont la méthode est invoquée faisant partie de l'environnement. Et pourquoi la
SomeClass
part de résultat? Parce que sonsomething
état aurait pu changer aussi!la source
test: <environment, number, number> -> <environment, number>
il devrait donc l'êtrea.F(b, c)
peut être considéré comme du sucre syntaxiqueF(a, b, c)
avec une règle spéciale à envoyer aux définitions surchargées de enF
fonction du type dea
(c'est en fait ainsi que Python le représente). Maisa
est toujours explicite dans les deux notations, alors que l'environnement dans une fonction non pure n'est jamais mentionné dans le code source.Les fonctions pures renvoient toujours la même valeur pour la même entrée. Les fonctions pures sont prévisibles et transparentes référentielles, ce qui signifie que nous pouvons remplacer l'appel de fonction par la sortie renvoyée et cela ne changera pas le fonctionnement du programme.
https://github.com/MostlyAdequate/mostly- CORRECTate-guide/blob/master/ch3.md
la source
En plus des autres réponses qui soulignent correctement en quoi cette fonction est non déterministe, elle a également un effet secondaire: elle entraînera les futurs appels
math.random()
à renvoyer une réponse différente. Et un générateur de nombres aléatoires qui n'a pas cette propriété effectuera généralement une sorte d'E / S, comme la lecture à partir d'un périphérique aléatoire fourni par le système d'exploitation. Soit est verboten pour une fonction pure.la source
Non, ça ne l'est pas. Vous ne pouvez pas du tout comprendre le résultat, donc ce morceau de code ne peut pas être testé. Pour rendre ce code testable, vous devez extraire le composant qui génère le nombre aléatoire:
Maintenant, vous pouvez vous moquer du générateur et tester correctement votre code:
Et dans votre code "production":
la source
util.Random
, que vous pouvez amorcer au début d'une exécution de test pour répéter l'ancien comportement ou pour une nouvelle (mais répétable) exécution. En cas de multi-threading, vous pourrez peut-être le faire dans le thread principal et l'utiliserRandom
pour amorcer des threads locaux répétablesRandom
. Cependant, si je comprends bien,test(int,int,Random)
n'est pas considéré comme pur car il modifie l'état duRandom
.Seriez-vous d'accord avec ce qui suit:
être équivalent à
?
Vous voyez, la définition de pure est une fonction dont la sortie ne change pas avec autre chose que ses entrées. Si nous disons que JavaScript avait un moyen de marquer une fonction pure et d'en tirer parti, l'optimiseur serait autorisé à réécrire la première expression en tant que seconde.
J'ai une expérience pratique dans ce domaine. Serveur SQL autorisé
getdate()
etnewid()
dans les fonctions "pures" et l'optimiseur dédupliquerait les appels à volonté. Parfois, cela ferait quelque chose de stupide.la source