Quels sont les avantages et les limites des langages de type dynamiques par rapport aux langages de type statiques?
Voir aussi : ce qui est avec l'amour des langages dynamiques (un fil beaucoup plus argumentatif ...)
Quels sont les avantages et les limites des langages de type dynamiques par rapport aux langages de type statiques?
Voir aussi : ce qui est avec l'amour des langages dynamiques (un fil beaucoup plus argumentatif ...)
Réponses:
La capacité de l'interpréteur à déduire le type et les conversions de type accélère le temps de développement, mais il peut également provoquer des échecs d'exécution que vous ne pouvez tout simplement pas obtenir dans un langage typé où vous les interceptez au moment de la compilation. Mais lequel est le meilleur (ou même si c'est toujours vrai) est chaudement discuté dans la communauté ces jours-ci (et depuis longtemps).
Un bon point de vue sur le problème vient de Typing Static Where Possible, Dynamic Typing When Needed: The End of the Cold War Between Programming Languages par Erik Meijer et Peter Drayton chez Microsoft:
la source
Les systèmes de type statique cherchent à éliminer statiquement certaines erreurs, inspectant le programme sans l'exécuter et essayant de prouver la solidité à certains égards. Certains systèmes de types sont capables de détecter plus d'erreurs que d'autres. Par exemple, C # peut éliminer les exceptions de pointeur nul lorsqu'il est utilisé correctement, alors que Java n'a pas un tel pouvoir. Twelf a un système de type qui garantit effectivement que les preuves se termineront , "résolvant" le problème d'arrêt .
Cependant, aucun système de type n'est parfait. Afin d'éliminer une classe particulière d'erreurs, ils doivent également rejeter certains programmes parfaitement valides qui violent les règles. C'est pourquoi Twelf ne résout pas vraiment le problème d'arrêt, il l'évite simplement en jetant un grand nombre de preuves parfaitement valides qui se terminent de façon étrange. De même, le système de type Java rejette l'
PersistentVector
implémentation de Clojure en raison de son utilisation de tableaux hétérogènes. Il fonctionne au moment de l'exécution, mais le système de type ne peut pas le vérifier.Pour cette raison, la plupart des systèmes de type fournissent des "échappements", des moyens de remplacer le vérificateur statique. Pour la plupart des langages, ceux-ci prennent la forme d'un casting, bien que certains (comme C # et Haskell) aient des modes entiers qui sont marqués comme "dangereux".
Subjectivement, j'aime la frappe statique. Implémenté correctement (indice: pas Java), un système de type statique peut être d'une grande aide pour éliminer les erreurs avant qu'elles ne plantent le système de production. Les langages typés dynamiquement ont tendance à nécessiter plus de tests unitaires, ce qui est fastidieux dans le meilleur des cas. En outre, les langages typés statiquement peuvent avoir certaines fonctionnalités qui sont soit impossibles soit dangereuses dans les systèmes de type dynamique (des conversions implicites viennent à l'esprit). Tout est une question d'exigences et de goût subjectif. Je ne construirais pas plus la prochaine Eclipse dans Ruby que je n'essaierais d'écrire un script de sauvegarde dans Assembly ou de corriger un noyau en utilisant Java.
Oh, et les gens qui disent que "la frappe x est 10 fois plus productive que la frappe y " soufflent simplement de la fumée. Typage dynamique peut « sentir » plus rapide dans de nombreux cas, mais il perd du terrain une fois que vous essayez réellement de faire votre demande de fantaisie terme . De même, le typage statique peut sembler être le filet de sécurité parfait, mais un coup d'œil à certaines des définitions de types génériques les plus compliquées de Java envoie la plupart des développeurs à la recherche de œillères. Même avec les systèmes de type et la productivité, il n'y a pas de solution miracle.
Remarque finale: ne vous inquiétez pas des performances lors de la comparaison de la frappe statique avec la frappe dynamique. Les JIT modernes comme V8 et TraceMonkey se rapprochent dangereusement des performances du langage statique. De plus, le fait que Java se compile en un langage intermédiaire intrinsèquement dynamique devrait être un indice que, dans la plupart des cas, la frappe dynamique n'est pas l'énorme performance-killer que certaines personnes prétendent être.
la source
dadd
parce qu'il sait à l'avance que les opérandes sontdouble
s.Eh bien, les deux sont très, très très très mal compris et aussi deux choses complètement différentes. qui ne s'excluent pas mutuellement .
Les types statiques sont une restriction de la grammaire de la langue. On pourrait dire que les langages typés statiquement ne sont pas dépourvus de contexte. La simple vérité est qu'il devient gênant d'exprimer un langage sainement dans des grammaires sans contexte qui ne traitent pas toutes ses données simplement comme des vecteurs de bits. Les systèmes de type statiques font partie de la grammaire du langage, le cas échéant, ils la restreignent simplement plus qu'une grammaire sans contexte pourrait le faire, les vérifications grammaticales se produisent donc en deux passages sur la source. Les types statiques correspondent à la notion mathématique de la théorie des types, la théorie des types en mathématiques restreint simplement la légalité de certaines expressions. Comme, je ne peux pas dire
3 + [4,7]
en mathématiques, c'est à cause de la théorie des types.Les types statiques ne sont donc pas un moyen de «prévenir les erreurs» d'un point de vue théorique, ils sont une limitation de la grammaire. En effet, à condition que +, 3 et les intervalles aient les définitions théoriques habituelles de l'ensemble, si nous supprimons le système de type, le résultat
3 + [4,7]
est assez bien défini, c'est un ensemble. les «erreurs de type d'exécution» n'existent théoriquement pas, l'utilisation pratique du système de type est d'empêcher des opérations qui pour les êtres humains n'auraient aucun sens. Bien sûr, les opérations ne sont que le déplacement et la manipulation de bits.L'inconvénient est qu'un système de type ne peut pas décider si de telles opérations vont se produire ou non s'il est autorisé à s'exécuter. Comme dans, partitionnez exactement l'ensemble de tous les programmes possibles dans ceux qui vont avoir une «erreur de type» et ceux qui ne le sont pas. Il ne peut faire que deux choses:
1: prouver que les erreurs de type vont se produire dans un programme
2: prouver qu'elles ne vont pas se produire dans un programme
Cela peut sembler me contredire. Mais ce qu'un vérificateur de type C ou Java fait, c'est qu'il rejette un programme comme «non grammatical», ou comme il l'appelle «erreur de type» s'il ne réussit pas à 2. Il ne peut pas prouver qu'il ne se produira pas, cela ne signifie pas qu'ils ne se produiront pas, cela signifie simplement que cela ne peut pas le prouver. Il se pourrait très bien qu'un programme qui n'aura pas d'erreur de type soit rejeté simplement parce qu'il ne peut pas être prouvé par le compilateur. Un exemple simple étant
if(1) a = 3; else a = "string";
, car c'est toujours vrai, la branche else ne sera jamais exécutée dans le programme et aucune erreur de type ne se produira. Mais il ne peut pas prouver ces cas de manière générale, il est donc rejeté. C'est la principale faiblesse de beaucoup de langages typés statiquement, en vous protégeant contre vous-même, vous êtes nécessairement aussi protégé dans les cas où vous n'en avez pas besoin.Mais, contrairement à la croyance populaire, il existe également des langages typés statiquement qui fonctionnent selon le principe 1. Ils rejettent simplement tous les programmes dont ils peuvent prouver que cela va provoquer une erreur de type et transmettent tous les programmes dont ils ne peuvent pas. Il est donc possible qu'ils autorisent les programmes qui contiennent des erreurs de type, un bon exemple étant Typed Racket, il est hybride entre le typage dynamique et statique. Et certains diront que vous obtenez le meilleur des deux mondes dans ce système.
Un autre avantage du typage statique est que les types sont connus au moment de la compilation et que le compilateur peut donc l'utiliser. Si nous, en Java, faisons
"string" + "string"
ou3 + 3
, les deux+
jetons dans le texte à la fin représentent une opération et une donnée complètement différentes, le compilateur sait lequel choisir parmi les types seuls.Maintenant, je vais faire une déclaration très controversée ici, mais gardez avec moi: le «typage dynamique» n'existe pas .
Cela semble très controversé, mais c'est vrai, les langages typés dynamiquement sont d'un point de vue théorique non typés . Ce ne sont que des langages typés statiquement avec un seul type. Autrement dit, ce sont des langues qui sont en effet générées grammaticalement par une grammaire sans contexte dans la pratique.
Pourquoi n'ont-ils pas de types? Parce que chaque opération est définie et autorisée sur chaque opérateur, qu'est-ce qu'une «erreur de type d'exécution» exactement? C'est à partir d'un exemple théorique purement un effet secondaire . Si faire
print("string")
qui imprime une chaîne est une opération, alorslength(3)
la première a pour effet secondaire d'écrirestring
sur la sortie standard, la seconde simplementerror: function 'length' expects array as argument.
, c'est tout. D'un point de vue théorique, une langue typée dynamiquement n'existe pas. Ils ne sont pas typésTrès bien, l'avantage évident du langage «typé dynamiquement» est le pouvoir expressif, un système de type n'est rien d'autre qu'une limitation du pouvoir expressif. Et en général, les langues avec un système de type auraient en effet un résultat défini pour toutes ces opérations qui ne sont pas autorisées si le système de type était simplement ignoré, les résultats n'auraient tout simplement pas de sens pour les humains. De nombreuses langues perdent leur exhaustivité de Turing après avoir appliqué un système de type.
L'inconvénient évident est le fait que des opérations peuvent se produire, ce qui produirait des résultats insensés pour l'homme. Pour se prémunir contre cela, les langages typés dynamiquement redéfinissent généralement ces opérations, plutôt que de produire ce résultat insensé, ils le redéfinissent pour avoir pour effet secondaire d'écrire une erreur, et éventuellement d'arrêter complètement le programme. Ce n'est pas du tout une «erreur», en fait, la spécification de la langue implique généralement cela, c'est autant le comportement de la langue que l'impression d'une chaîne d'un point de vue théorique. Les systèmes de types obligent donc le programmeur à raisonner sur le flux du code pour s'assurer que cela ne se produit pas. Ou bien, raison pour qu'il nese produire peut également être utile à certains égards pour le débogage, montrant que ce n'est pas du tout une «erreur» mais une propriété bien définie du langage. En effet, le seul vestige de «typage dynamique» que la plupart des langues ont se garde contre une division par zéro. C'est ce qu'est la frappe dynamique, il n'y a pas de types, il n'y a pas plus de types que ce zéro est un type différent de tous les autres nombres. Ce que les gens appellent un «type» n'est qu'une autre propriété d'une donnée, comme la longueur d'un tableau ou le premier caractère d'une chaîne. Et de nombreuses langues typées dynamiquement vous permettent également d'écrire des choses comme
"error: the first character of this string should be a 'z'"
.Une autre chose est que les langages typés dynamiquement ont le type disponible au moment de l'exécution et peuvent généralement le vérifier et le traiter et en décider. Bien sûr, en théorie, ce n'est pas différent que d'accéder au premier caractère d'un tableau et de voir de quoi il s'agit. En fait, vous pouvez créer votre propre C dynamique, n'utilisez qu'un seul type comme long long int et utilisez les 8 premiers bits pour stocker votre `` type '' et écrire des fonctions en conséquence qui le vérifient et effectuent une addition flottante ou entière. Vous avez une langue typée statiquement avec un type ou une langue dynamique.
En pratique, tout cela montre que les langages typés statiquement sont généralement utilisés dans le contexte de l'écriture de logiciels commerciaux, tandis que les langages typés dynamiquement ont tendance à être utilisés dans le contexte de la résolution de certains problèmes et de l'automatisation de certaines tâches. L'écriture de code dans des langages typés prend simplement du temps et est fastidieuse car vous ne pouvez pas faire des choses qui vont bien se passer, mais le système de type vous protège toujours contre vous-même pour les erreurs que vous ne faites pas. De nombreux codeurs ne réalisent même pas qu'ils le font parce que c'est dans leur système, mais lorsque vous codez dans des langages statiques, vous contournez souvent le fait que le système de type ne vous laisse pas faire des choses qui ne peuvent pas mal tourner, car il ne peut pas prouver que ça ne va pas mal.
Comme je l'ai noté, «dactylographié» signifie généralement le cas 2, coupable jusqu'à preuve du contraire. Mais certains langages, qui ne tirent pas du tout leur système de types de la théorie des types, utilisent la règle 1: Innocent jusqu'à preuve du contraire, ce qui pourrait être l'hybride idéal. Alors, peut-être que Typed Racket est pour vous.
De plus, pour un exemple plus absurde et extrême, j'implémente actuellement un langage où les «types» sont vraiment le premier caractère d'un tableau, ce sont des données, des données de «type», «type», qui est lui-même un type et une donnée, la seule donnée qui a elle-même comme type. Les types ne sont pas finis ou limités statiquement, mais de nouveaux types peuvent être générés en fonction des informations d'exécution.
la source
Le plus grand "avantage" du typage dynamique est peut-être la courbe d'apprentissage moins profonde. Il n'y a pas de système de types à apprendre et pas de syntaxe non triviale pour les cas d'angle tels que les contraintes de type. Cela rend la frappe dynamique accessible à beaucoup plus de personnes et réalisable pour de nombreuses personnes pour lesquelles les systèmes sophistiqués de type statique sont hors de portée. Par conséquent, le typage dynamique a fait son chemin dans les contextes de l'éducation (par exemple Scheme / Python au MIT) et les langages spécifiques au domaine pour les non-programmeurs (par exemple Mathematica ). Les langages dynamiques ont également fait leur apparition dans des niches où ils ont peu ou pas de concurrence (par exemple Javascript).
Les langages à typage dynamique les plus concis (par exemple Perl, APL, J, K, Mathematica ) sont spécifiques à un domaine et peuvent être beaucoup plus concis que les langages à typage général à usage général les plus concis (par exemple OCaml ) dans les niches pour lesquelles ils ont été conçus. .
Les principaux inconvénients de la frappe dynamique sont:
Erreurs de type à l'exécution.
Il peut être très difficile, voire pratiquement impossible, d'atteindre le même niveau d'exactitude et nécessite beaucoup plus de tests.
Aucune documentation vérifiée par le compilateur.
Mauvaises performances (généralement au moment de l'exécution mais parfois au moment de la compilation à la place, par exemple Staline Scheme) et performances imprévisibles en raison de la dépendance à des optimisations sophistiquées.
Personnellement, j'ai grandi sur les langages dynamiques mais je ne les toucherais pas avec un poteau de 40 pieds en tant que professionnel à moins qu'il n'y ait pas d'autres options viables.
la source
Extrait de Artima's Typing: Strong vs Weak, Static vs. Dynamic article:
Dans l'article de Pascal Costanza, Dynamic vs. Static Typing - A Pattern-Based Analysis (PDF), il affirme que dans certains cas, le typage statique est plus sujet aux erreurs que le typage dynamique. Certaines langues typées statiquement vous obligent à émuler manuellement la frappe dynamique afin de faire "The Right Thing". Il en est question à Lambda the Ultimate .
la source
Cela dépend du contexte. Il y a beaucoup d'avantages qui conviennent au système typé dynamique ainsi qu'au typage fort. Je suis d'avis que le flux de langage de types dynamiques est plus rapide. Les langages dynamiques ne sont pas limités par les attributs de classe et le compilateur pensant à ce qui se passe dans le code. Vous avez un peu de liberté. De plus, le langage dynamique est généralement plus expressif et entraîne moins de code, ce qui est bien. Malgré cela, il est plus sujet aux erreurs, ce qui est également discutable et dépend davantage de la couverture du test unitaire. C'est un prototype facile avec une langue dynamique mais la maintenance peut devenir un cauchemar.
Le principal gain par rapport au système de type statique est le support IDE et sûrement l'analyseur de code statique. Vous devenez plus sûr du code après chaque changement de code. L'entretien est la paix du gâteau avec de tels outils.
la source
Il y a beaucoup de choses différentes sur les langages statiques et dynamiques. Pour moi, la principale différence est que dans les langages dynamiques, les variables n'ont pas de types fixes; au lieu de cela, les types sont liés à des valeurs. Pour cette raison, le code exact qui est exécuté est indéterminé jusqu'à l'exécution.
Dans les implémentations précoces ou naïves, cela représente un énorme frein aux performances, mais les JIT modernes se rapprochent énormément du meilleur que vous pouvez obtenir avec l'optimisation des compilateurs statiques. (dans certains cas marginaux, encore mieux que cela).
la source
Il s'agit du bon outil pour le travail. Ni mieux à 100% du temps. Les deux systèmes ont été créés par l'homme et ont des défauts. Désolé, mais on craint et on fait des trucs parfaits.
J'aime la frappe dynamique car elle me gêne, mais oui, des erreurs d'exécution peuvent se produire que je n'avais pas prévues. Alors que le typage statique peut corriger les erreurs susmentionnées, mais rendre fou un programmeur novice (dans les langages typés) qui essaie de passer entre un caractère constant et une chaîne.
la source
Typage statique: les langages tels que Java et Scala sont typés statiquement.
Les variables doivent être définies et initialisées avant d'être utilisées dans un code.
par ex. int x; x = 10;
System.out.println (x);
Typage dynamique: Perl est un langage typé dynamique.
Les variables n'ont pas besoin d'être initialisées avant d'être utilisées dans le code.
y = 10; utiliser cette variable dans la dernière partie du code
la source