Fonction pure - Pure function

En programmation informatique , une fonction pure est une fonction qui a les propriétés suivantes :

  1. La fonction des valeurs de retour sont identiques pour les mêmes arguments (pas de variation locale avec des variables statiques , variables non locales , mutables arguments de référence ou les flux d' entrée ).
  2. L' application de la fonction n'a pas d' effets secondaires (pas de mutation de variables statiques locales, de variables non locales, d'arguments de référence mutables ou de flux d'entrée/sortie).

Ainsi, une fonction pure est un analogue informatique d'une fonction mathématique . Certains auteurs, en particulier de la communauté des langages impératifs, utilisent le terme "pur" pour toutes les fonctions qui ont juste la propriété ci-dessus 2 (discutée ci - dessous ).

Exemples

Fonctions pures

Les exemples suivants de fonctions C++ sont purs :

  • floor, retournant la parole d'un nombre ;
  • max, renvoyant le maximum de deux valeurs.
  • la fonction f , définie comme
    void f() {
      static std::atomic<unsigned int> x = 0;
      ++x;
    }
    
    Bien que cet exemple de code semble ne pas être pur, il l'est en réalité. La valeur de xne peut être observée qu'à l'intérieur d'autres invocations de f(), et comme f()ne communique pas la valeur de xà son environnement, elle est indiscernable d'une fonction void f() {}qui ne fait rien. Notez que xc'est std::atomicpour que les modifications de plusieurs threads s'exécutant f()simultanément n'entraînent pas une course de données , qui a un comportement indéfini en C et C++.

Fonctions impures

Les fonctions C++ suivantes sont impures car il leur manque la propriété ci-dessus 1 :

  • à cause de la variation de la valeur de retour avec une variable statique
    int f() {
      static int x = 0;
      ++x;
      return x;
    }
    
  • en raison de la variation de la valeur de retour avec une variable non locale
    int f() {
      return x;
    }
    
    Pour la même raison, par exemple, la fonction de bibliothèque C++ sin()n'est pas pure, puisque son résultat dépend du mode d'arrondi IEEE qui peut être modifié au moment de l'exécution.
  • en raison de la variation de la valeur de retour avec un argument de référence modifiable
    int f(int* x) {
      return *x;
    }
    
  • en raison de la variation de la valeur de retour avec un flux d'entrée
    int f() {
      int x = 0;
      std::cin >> x;
      return x;
    }
    

Les fonctions C++ suivantes sont impures car il leur manque la propriété ci-dessus 2 :

  • à cause de la mutation d'une variable statique locale
    void f() {
      static int x = 0;
      ++x;
    }
    
  • à cause de la mutation d'une variable non locale
    void f() {
      ++x;
    }
    
  • à cause de la mutation d'un argument de référence mutable
    void f(int* x) {
      ++*x;
    }
    
  • à cause de la mutation d'un flux de sortie
    void f() {
      std::cout << "Hello, world!" << std::endl;
    }
    

Les fonctions C++ suivantes sont impures car il leur manque à la fois les propriétés 1 et 2 ci-dessus :

  • en raison de la variation de la valeur de retour avec une variable statique locale et de la mutation d'une variable statique locale
    int f() {
      static int x = 0;
      ++x;
      return x;
    }
    
  • en raison de la variation de la valeur de retour avec un flux d'entrée et de la mutation d'un flux d'entrée
    int f() {
      int x = 0;
      std::cin >> x;
      return x;
    }
    

E/S en fonctions pures

Les E/S sont par nature impures : les opérations d'entrée minent la transparence référentielle et les opérations de sortie créent des effets secondaires. Néanmoins, il existe un sens dans lequel la fonction peut effectuer une entrée ou une sortie et être toujours pure, si la séquence d'opérations sur les périphériques d'E/S concernés est modélisée explicitement à la fois comme un argument et un résultat, et que les opérations d'E/S sont prises en compte. échoue lorsque la séquence d'entrée ne décrit pas les opérations réellement effectuées depuis le début de l'exécution du programme.

Le deuxième point garantit que la seule séquence utilisable comme argument doit changer à chaque action d'E/S ; le premier permet à différents appels à une fonction exécutant des E/S de renvoyer des résultats différents en raison de la modification des arguments de séquence.

La monade d'E/S est un idiome de programmation généralement utilisé pour effectuer des E/S dans des langages fonctionnels purs.

Optimisations du compilateur

Les fonctions qui ont juste la propriété ci-dessus 2 permettent des techniques d'optimisation de compilateur telles que l'élimination de sous-expression commune et l' optimisation de boucle similaires aux opérateurs arithmétiques. Un exemple C++ est la lengthméthode, retournant la taille d'une chaîne, qui dépend du contenu de la mémoire vers laquelle la chaîne pointe, donc sans la propriété 1 ci-dessus. Néanmoins, dans un environnement monothread , le code C++ suivant

std::string s = "Hello, world!";
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int l = 0;

for (int i = 0; i < 10; ++i) {
  l += s.length() + a[i];
}

peut être optimisé de telle sorte que la valeur de s.length()est calculée une seule fois, avant la boucle.

Certains langages de programmation permettent de déclarer une propriété pure à une fonction :

  • En Fortran et D, le puremot - clé peut être utilisé pour déclarer une fonction sans effet secondaire (c'est-à-dire n'avoir que la propriété ci-dessus 2). Le compilateur peut être en mesure de déduire la propriété 1 en plus de la déclaration.
  • Dans le GCC , l' pureattribut spécifie la propriété 2, tandis que l' constattribut spécifie une fonction vraiment pure avec les deux propriétés.
  • Les langages offrant l' exécution de fonctions au moment de la compilation peuvent exiger que les fonctions soient pures, parfois avec l'ajout d'autres contraintes. Les exemples incluent constexprC++ (les deux propriétés).

Tests unitaires

Puisque les fonctions pures ont des valeurs de retour identiques pour des arguments identiques , elles sont bien adaptées aux tests unitaires .

Voir également

Les références