web-dev-qa-db-fra.com

Pourquoi les fonctions impures sont-elles dites non composables?

Je comprends ce que sont les fonctions pures et quand quelqu'un dit que les fonctions pures sont composables - je crois que cela signifie que la sortie d'une fonction peut être transmise comme entrée à une autre fonction, mais la même chose vaut également pour les fonctions impures, n'est-ce pas? Prenez les deux fonctions ci-dessous:

int sum(int a, int b) {
    print("sum");
    return a + b;
}

void save(int result) {
    DB.save(result);
}

void PersistSum(int a, int b) {
    save(sum(a,b));
}

Bien que les fonctions save et sum aient des effets secondaires - elles peuvent toujours être composées comme dans PersistSum

Je suis sûr qu'il manque ici une signification fondamentale de la composabilité. Quelqu'un peut-il donner une signification précise de ce que signifie la composabilité et pourquoi les fonctions ayant des effets secondaires ne sont pas composables avec un exemple?

7
rahulaga_dev

Composition des fonctions crée en effet une nouvelle fonction qui applique une fonction à la sortie d'une autre. Plus généralement , la composition permet de créer une nouvelle fonction en combinant plusieurs autres fonctions.

fonctions pures sont des fonctions qui fournissent toujours la même sortie pour la même entrée et n'ont aucun effet secondaire. C'est donc une fonction sans surprise, que vous pouvez appeler à quelle fréquence vous en avez besoin puisque seul son résultat compte.

Vous pouvez composer des fonctions pures. Vous obtiendrez, par définition, une fonction pure.

Vous pouvez également composer des fonctions impures. C'est juste que c'est plus risqué.

Prenons un exemple avec h(x) = g (f (x)):

  • Si f et g ont deux effets secondaires totalement indépendants, sf et sg, ces effets secondaires se produiront dans l'ordre suivant: d'abord sf, puis sg.
  • Si les effets secondaires ne sont pas indépendants, la composition peut avoir des effets inattendus.

Supposons maintenant que vous avez une composition plus complexe, utilisant plusieurs variables et plus de deux fonctions: h (x, y) = g (f1 (x, y), f2 (x, y)). Comme déjà dit, si toutes ces fonctions sont pures, le résultat sera pur sans surprise. Si ces fonctions sont impures, de nombreuses questions restent ouvertes:

  • Supposons que chacune de ces fonctions ait des effets secondaires indépendants sg, sf1, sf2. Ici, vous ne pouvez plus prédire l'ordre de ces effets secondaires: ce pourrait être sf1, sf2, sg. Cela pourrait aussi bien être sf2 sf1 sg ou même sf1 et sf2 exactement en même temps, puis sg.
  • Supposons que ces effets secondaires ne soient pas indépendants, par exemple que sf1 ajoute 1 à une variable globale et sf2 multiplie par 2 les mêmes variables globales, l'effet de h sur la variable globale serait imprévisible.
13
Christophe

Les expressions avec des fonctions pures peuvent être réécrites, puis les effets secondaires se produisent différemment.

f x = { print(x), x }
^ (xor) is commutative an associative, x ^ 0 == x, x ^ x == 0

Cela peut être utilisé pour filtrer les doublons, en recourant aux termes:

f 3 ^ f 5 ^ f 7 ^ f 5 ^ f 3 ==
(f 3 ^ f 3) ^ (f 5 ^ f 5) ^ f 7  ==
0 ^ 0 ^ f 7 ==
f 7 ==                     -- Just one print(7)
7

Les effets secondaires peuvent donc se produire dans différents ordres ou pas du tout, s'ils sont ignorés.

Mon point: composition de la fonction concerne également les opérations d'arbre d'expression.

(Gardez également à l'esprit qu'il n'y a aucune garantie que deux appels avec les mêmes arguments donneront le même résultat. Mais cet aspect que vous n'aviez pas voulu.)

1
Joop Eggen