Forum Programmation.autre Rust : lapin compris les durées de vie

Posté par  . Licence CC By‑SA.
Étiquettes :
1
29
juin
2021

Bonjours mesdames messieurs,
J'essaye de me rafraîchir la mémoire sur le langage Rust, que je n'ai pas pratiqué depuis 1 ou 2 ans. Pour cela je lis «The Rust Programming Language», document officiel qui décrit ses caractéristiques.
Arrivé au chapitre 10.3 sur les durées de vie, je me retrouve face à une question sans réponse.

On nous présente ce bout de code :

    fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
        if x.len() > y.len() {
            x
        } else {
            y
        }
    }

On nous explique qu'on est obligé de spécifier la durée de vie «'a» sur les deux entrées et sur la sortie de la fonction. L'explication, c'est que le compilateur ne sait pas si c'est une référence vers x ou y qui va sortir, donc il ne sait pas quelle durée de vie vérifier. Je comprends bien cette contrainte, en effet l'emprunt du if ou du else sera décidé à l'exécution.

Ce que je ne comprends pas, c'est pourquoi, dans ce cas là, le compilateur ne liste pas toutes les possibilités, puis s'appuie sur la durée de vie la plus limitée ? Pour reprendre l'exemple plus haut, pourquoi le compilateur ne peut-il pas suivre cet algorithme :

  1. Lister toutes les références qui peuvent atterrir en sortie (ici donc, x et y)
  2. Estimer la durée de vie de chacune
  3. Choisir la plus mauvaise, comme ça on évite les erreurs de référence nulle

Pourquoi est-ce qu'on doit utiliser cette syntaxe «'a» pour lui dire de le faire ? Ne peut-il pas le faire sans qu'on lui demande ?

Merci d'avance !

  • # Pour éviter les comportements non voulus ?

    Posté par  . Évalué à 4. Dernière modification le 29/06/21 à 19:32.

    parce que le compilateur ne doit pas décider à ta place dans ce genre de cas. C'est toi le développeur qui doit connaitre cette information … Perso je préfère que le compilo ne prenne pas de décision et me prévienne d'un potentiel problèmen, plutôt que de prendre une décision qui ne serait pas la bonne sans me prévenir.

    Un exemple que j'ai à l'esprit, c'est la conversion de types implicite en Java : même si c'est documenté le compilateur prend des décisions pour toi qui peuvent ne pas être celle que tu veux. Je préfère un compilateur qui me dit "eh, ya un truc qui va pas là, regarde ce qui se passe" …

    • [^] # Re: Pour éviter les comportements non voulus ?

      Posté par  . Évalué à 2.

      Je plussoie, c'est clairement au développeur de connaître cette information et de l'indiquer au compilateur.

      Si tu appliquais "le pire cas", tu donnerais implicitement du sens à une formulation ambigüe. Si tu es dans un cas où il y aurait seulement une des lifetimes dans la sortie, tu créerai implicitement une contrainte forte sur la durée de vie de tes paramètres --> Des messages d'erreurs cryptiques sur des références qui ne vivent pas assez longtemps seraient remontés par le compilateurs.

      Le point problématique est: "sens implicite à une formulation ambigüe".

      Pour éviter celà, les règles d'elision interdisent ce que tu décris.

  • # Unification des types

    Posté par  (site Web personnel) . Évalué à 4.

    (Note : je ne connais pas Rust, il est donc possible que ma syntaxe ne soit pas propre)

    La syntaxe 'a permet de définir une contrainte dans la signature de la fonction. Ce qui est important ici n'est pas d'ajouter l'information sur la durée de vie : ce qui est important est que cette information de durée de vie soit la même sur l'ensemble des termes passés en arguments.

    Tu pourrais avoir cette fonction qui prend en paramètre des arguments avec des durées de vie différents :

      fn longest<'a, b>(x: &'a str, y: &'b str) ->

    Le problème qui se pose ici est de définir le résultat de la fonction. Garde à l'esprit qu'il faut que cela soit exprimable dans le langage. Comment représentes-tu prends la durée de vie la plus mauvaise des deux ? (C'est peut être possible, j'ignore a quel point le système de type de rust est avancé. Il faudrait pour cela que la durée de vie puisse être représenté par un type arbitraire).

    On pourrait décider de prendre arbitrairement l'un ou l'autre :

      fn longest<'a, b>(x: &'a str, y: &'b str) -> &'b str

    mais le compilateur risque de ne pas aimer et lever l'erreur en indiquant une incohérence dans le code.

    Le plus simple est donc d'imposer cette contrainte : les deux types doivent avoir la même durée de vie, et c'est à l'appelant de s'assurer que cette contrainte est respectée.

  • # Merci

    Posté par  . Évalué à 1.

    Merci pour vos réponses, je comprends qu'il s'agit surtout de faire en sorte que le programmeur ait pleine conscience de ce qu'il se passe avec les durées de vie.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.