2

Je travaille sur un cours Coursera sur la programmation fonctionnelle et discute à un moment donné de la différence entre les techniques d'évaluation call-by-value et call-by-name. Ils sont un point qui me confond, disent-ils:Équivalence call-by-name et par nom

Les deux techniques permettent de réduire les mêmes valeurs finales aussi longtemps que:

  1. les expressions réduites se compose de fonctions pures et
  2. les deux évaluations se terminent

qui semble être un théorème de lambda-calcul. Pourriez-vous m'expliquer ce qu'ils entendent par "les expressions réduites conssist des fonctions pures"?

+2

Avez-vous regardé https://en.wikipedia.org/wiki/Pure_function? – Bergi

+0

Il y a beaucoup de références dans ce cours à d'autres matériels d'apprentissage. Il serait préférable de les vérifier d'abord ou d'utiliser un forum de cours. – Pavel

+1

@Rodrigo Ceci est une déclaration informelle du [théorème de Church-Rosser] (https://en.wikipedia.org/wiki/Church%E2%80%93Rosser_theorem), par lequel le lambda-calcul est confluent. La phrase à laquelle vous faites référence est probablement seulement là parce que l'utilisation du théorème pour Scala est un léger abus de terminologie, puisqu'elle ne s'applique qu'à un certain sous-ensemble pur du langage. – phg

Répondre

4

Une fonction pure est une fonction qui n'a pas d'effets secondaires (comme faire des E/S ou modifier une valeur qui n'est pas locale à la fonction). Un exemple d'une pure fonction serait:

def inc(x: Int) = x+1 

Un exemple d'une fonction impure serait:

var sum = 1 
def addToSum(x: Int) = { 
    sum += x 
    sum 
} 

Alors maintenant, nous allons examiner les deux méthodes suivantes, qui ne diffèrent que par le fait que ils prennent leurs arguments par nom ou valeur:

def doubleByValue(x: Int) = x + x 
def doubleByName(x: =>Int) = x + x 

maintenant, si nous utilisons ces deux avec la fonction pure, le résultat est le même:

doubleByValue(inc(2)) // => 6 
doubleByName(inc(2)) // => 6 

Mais si nous les appliquons à la fonction impure, le résultat est différent:

sum = 1 // Let's reset sum, so the result isn't affected by previous uses 
doubleByValue(addToSum(2)) // => 6, the value of `sum` is now 3 
sum = 1 // Let's reset sum, so the result isn't affected by previous uses 
doubleByName(addToSum(2)) // => 8, the value of `sum` is now 5 

La différence est que la version ByName appelle la fonction deux fois et ajoute les deux résultats, alors que la version une fois appelle ByValue , enregistre le résultat et l'ajoute à lui-même. Pour la fonction pure, cela ne fait absolument aucune différence - étant donné le même argument, le résultat sera toujours le même, cela ne fait aucune différence si vous l'appelez une fois et utilisez deux fois le résultat enregistré ou deux fois (sauf pour la performance).

Pour la fonction impure, cela fait une grande différence puisque la valeur de la variable sum est modifiée chaque fois que la fonction est appelée.