Je n'ai jamais compris des déclarations comme celle-ci. Pour être honnête, même si vous déclarez le type de retour d'une fonction, vous pouvez et vous l'oublierez après avoir écrit de nombreuses lignes de code, et vous devrez toujours revenir à la ligne dans laquelle il est déclaré à l'aide de la fonction de recherche de votre éditeur de texte pour le vérifier.
Il ne s'agit pas d'oublier le type de retour - cela va toujours arriver. Il s'agit de l'outil capable de vous faire savoir que vous avez oublié le type de retour.
De plus, comme les fonctions sont déclarées avec type funcname()...
, sans connaître le type, vous devrez rechercher sur chaque ligne dans laquelle la fonction est appelée, car vous ne le savez funcname
, tandis qu'en Python et autres, vous pouvez simplement rechercher def funcname
ou function funcname
ce qui ne se produit qu'une seule fois , lors de la déclaration.
C'est une question de syntaxe, qui n'a aucun lien avec le typage statique.
La syntaxe de la famille C est en effet peu conviviale lorsque vous souhaitez rechercher une déclaration sans disposer d'outils spécialisés. Les autres langues n'ont pas ce problème. Voir la syntaxe de déclaration de Rust:
fn funcname(a: i32) -> i32
De plus, avec les REPL, il est trivial de tester une fonction pour son type de retour avec différentes entrées, tandis qu'avec les langages typés statiquement, vous devrez ajouter quelques lignes de code et tout recompiler juste pour connaître le type déclaré.
Toute langue peut être interprétée et toute langue peut avoir un REPL.
Donc, à part connaître le type de retour d'une fonction qui n'est clairement pas un point fort des langages typés statiquement, en quoi le typage statique est-il vraiment utile dans les grands projets?
Je répondrai de manière abstraite.
Un programme se compose de diverses opérations et ces opérations sont présentées telles qu'elles sont en raison de certaines hypothèses émises par le développeur.
Certaines hypothèses sont implicites et d'autres sont explicites. Certaines hypothèses concernent une opération à proximité, certaines concernent une opération à distance. Une hypothèse est plus facile à identifier lorsqu'elle est exprimée explicitement et le plus près possible des endroits où sa valeur de vérité est importante.
Un bogue est la manifestation d'une hypothèse qui existe dans le programme mais qui ne tient pas dans certains cas. Pour retrouver un bogue, nous devons identifier l'hypothèse erronée. Pour supprimer le bogue, nous devons soit supprimer cette hypothèse du programme, soit modifier quelque chose pour que l'hypothèse se vérifie.
Je voudrais classer les hypothèses en deux types.
Le premier type sont les hypothèses qui peuvent ou non tenir, selon les entrées du programme. Pour identifier une hypothèse erronée de ce type, nous devons rechercher dans l'espace toutes les entrées possibles du programme. En utilisant des suppositions éclairées et une pensée rationnelle, nous pouvons affiner le problème et chercher dans un espace beaucoup plus petit. Mais quand un programme se développe encore un peu, son espace d'entrée initial augmente à un rythme énorme - au point où il peut être considéré comme infini à toutes fins pratiques.
Le deuxième type sont les hypothèses qui valent définitivement pour toutes les entrées, ou qui sont définitivement erronées pour toutes les entrées. Lorsque nous identifions une hypothèse de ce type comme erronée, nous n'avons même pas besoin d'exécuter le programme ou de tester une entrée. Lorsque nous identifions une hypothèse de ce type comme correcte, nous avons un suspect de moins à prendre en compte lorsque nous recherchons un bogue ( n'importe quel bogue). Par conséquent, il est utile que le plus grand nombre possible d'hypothèses appartiennent à ce type.
Pour placer une hypothèse dans la deuxième catégorie (toujours vrai ou toujours faux, indépendamment des entrées), nous avons besoin d'un minimum d'informations pour être disponible à l'endroit où l'hypothèse est faite. Dans le code source d'un programme, les informations deviennent périmées assez rapidement (par exemple, de nombreux compilateurs ne font pas d'analyse interprocédurale, ce qui fait de tout appel une limite stricte pour la plupart des informations). Nous avons besoin d'un moyen de garder à jour les informations requises (valides et à proximité).
Une façon consiste à avoir la source de ces informations aussi près que possible de l'endroit où elles vont être consommées, mais cela peut ne pas être pratique pour la plupart des cas d'utilisation. Une autre façon consiste à répéter fréquemment les informations, en renouvelant leur pertinence dans le code source.
Comme vous pouvez déjà le deviner, les types statiques sont exactement cela - des balises d'informations de type dispersées à travers le code source. Ces informations peuvent être utilisées pour placer la plupart des hypothèses sur l'exactitude des types dans la deuxième catégorie, ce qui signifie que presque toutes les opérations peuvent être classées comme toujours correctes ou toujours incorrectes en ce qui concerne la compatibilité des types.
Lorsque nos types sont incorrects, l'analyse nous fait gagner du temps en signalant le bogue plus tôt que tard. Lorsque nos types sont corrects, l'analyse nous fait gagner du temps en s'assurant que lorsqu'un bogue se produit, nous pouvons immédiatement exclure les erreurs de type.