web-dev-qa-db-fra.com

Avantages de la fonction pure

Aujourd'hui, je lisais à propos de la fonction pure, je me suis confondu avec son utilisation:

Une fonction est dite pure si elle renvoie un même ensemble de valeurs pour le même ensemble d'entrées et n'a pas d'effets secondaires observables.

par exemple. strlen() est une fonction pure Rand() est une impure.

__attribute__ ((pure)) int fun(int i)
{
    return i*i;
}

int main()
{
    int i=10;
    printf("%d",fun(i));//outputs 100
    return 0;
}

http://ideone.com/33xj

Le programme ci-dessus se comporte de la même manière que en l'absence de la déclaration pure.

Quels sont les avantages de déclarer une fonction comme pure [s'il n'y a pas de changement de sortie] ?

81
Green goblin

pure permet au compilateur savoir qu'il peut faire certaines optimisations sur la fonction: imaginez un peu de code comme

for (int i = 0; i < 1000; i++)
{
    printf("%d", fun(10));
}

Avec une fonction pure, le compilateur peut savoir qu'il doit évaluer fun(10) une fois et une fois seulement, plutôt que 1000 fois. Pour une fonction complexe, c'est une grosse victoire.

144
Philip Kendall

Lorsque vous dites qu'une fonction est "pure", vous garantissez qu'il n'y a pas d'effets secondaires visibles de manière externe (et comme un commentaire dit, si vous vous trouvez, de mauvaises choses peuvent arriver). Sachant qu'une fonction est "pure" présente des avantages pour le compilateur, qui peut utiliser ces connaissances pour effectuer certaines optimisations.

Voici ce que la Documentation GCC dit à propos de l'attribut pure:

pur

De nombreuses fonctions n'ont aucun effet, à l'exception de la valeur de retour et de leur valeur de retour ne dépend que des paramètres et/ou des variables globales. Une telle fonction peut être soumise à une allimination commune de la sous-experce et à une optimisation de la boucle, tout comme un opérateur arithmétique serait. Ces fonctions doivent être déclarées avec l'attribut pur. Par exemple,

          int square (int) __attribute__ ((pure));

Réponse de Philip montre déjà comment savoir une fonction est "pure" peut aider avec des optimisations en boucle.

Voici un pour l'élimination de la sous-expression commune (donné foo est pur):

a = foo (99) * x + y;
b = foo (99) * x + z;

Peut devenir:

_tmp = foo (99) * x;
a = _tmp + y;
b = _tmp + z;
34
ArjunShankar

Outre les éventuels avantages d'exécution, une fonction pure est beaucoup plus facile à motiver lorsque le code de lecture. En outre, il est beaucoup plus facile de tester une fonction pure puisque vous savez que la valeur de retour ne dépend que des valeurs des paramètres.

28
Frerich Raabe

Une fonction non pure

int foo(int x, int y) // possible side-effects

est comme une extension d'une fonction pure

int bar(int x, int y) // guaranteed no side-effects

dans lequel vous avez, outre les arguments de fonction explicite X, Y, le reste de l'univers (ou tout ce que votre ordinateur peut communiquer avec) comme une entrée potentielle implicite. De même, outre la valeur de retour entier explicite, tout ce que votre ordinateur peut écrire est implicitement une partie de la valeur de retour.

Il convient de préciser pourquoi il est beaucoup plus facile de raisonner sur une fonction pure qu'un non pur.

15
Giorgio

Tout comme un complément, je voudrais mentionner que C++ 11 codifie des choses quelque peu à l'aide du mot clé Constexpr. Exemple:

#include <iostream>
#include <cstring>

constexpr unsigned static_strlen(const char * str, unsigned offset = 0) {
        return (*str == '\0') ? offset : static_strlen(str + 1, offset + 1);
}

constexpr const char * str = "asdfjkl;";

constexpr unsigned len = static_strlen(str); //MUST be evaluated at compile time
//so, for example, this: int arr[len]; is legal, as len is a constant.

int main() {
    std::cout << len << std::endl << std::strlen(str) << std::endl;
    return 0;
}

Les restrictions sur l'utilisation de la consexpr en font de sorte que la fonction soit pratiquement pure. De cette façon, le compilateur peut optimiser plus agressivement (assurez-vous simplement d'utiliser la récursion de la queue, s'il vous plaît!) Et évaluez la fonction au moment de la compilation au lieu d'exécution.

Ainsi, pour répondre à votre question, c'est que si vous utilisez C++ (je sais que vous avez dit c, mais ils sont liés), écrire une fonction pure dans le bon style permet au compilateur de faire toutes sortes de choses cool avec la fonction: -)

7
Robert Mason

En général, les fonctions pures ont 3 avantages par rapport aux fonctions impures que le compilateur peut profiter de:

Cache

Disons que vous avez une fonction pure f qui est appelée 100 000 fois, car il est déterministe et dépend uniquement de ses paramètres, le compilateur peut calculer sa valeur une fois et l'utiliser si nécessaire

Parallélisme

Les fonctions pures ne lisent ni n'écrivent à aucune mémoire partagée et peuvent donc exécuter des threads séparés sans aucune conséquence inattendue.

Passage par référence

Une fonction f(struct t) obtient son argument t par valeur, et d'autre part, le compilateur peut passer t par référence à f si elle est déclarée déclarée comme pur tout en garantissant que la valeur de t ne changera pas de gains de performance


En plus des considérations d'heure de compilation, les fonctions pures peuvent être testées assez facilement: appelez-les simplement.

Pas besoin de construire des objets ou de simuler des connexions au système DBS/fichiers.

4
Uri Goren