181 votes

Chercher des éclaircissements sur les contradictions apparentes concernant les langues faiblement typées

Je crois que je comprends taper fort, mais chaque fois que je regarde pour les exemples de ce qui est faible en tapant-je trouver des exemples de langages de programmation que simplement forcer/convertir automatiquement des types.

Par exemple, dans cet article, nommé en Tapant: Forte vs Faible, Statique vs Dynamique dit que Python est fortement typé, parce que vous obtenez une exception si vous essayez de:

Python

1 + "1"
Traceback (most recent call last):
File "", line 1, in ? 
TypeError: unsupported operand type(s) for +: 'int' and 'str'

Cependant, une telle chose est possible en Java et en C#, et nous ne les considèrent pas comme faiblement typé juste pour ça.

Java

  int a = 10;
  String b = "b";
  String result = a + b;
  System.out.println(result);

C#

int a = 10;
string b = "b";
string c = a + b;
Console.WriteLine(c);

Dans cet autre article nommé Faiblement Type de Langues, l'auteur dit que Perl est faiblement typé tout simplement parce que je peux concaténer une chaîne en nombre, et vice-versa, sans aucune conversion explicite.

Perl

$a=10;
$b="a";
$c=$a.$b;
print $c; #10a

Donc, le même exemple fait Perl faiblement typé, mais pas Java et C#?.

Gee, c'est déroutant enter image description here

Les auteurs semblent impliquer qu'une langue qui empêche l'application de certaines opérations sur des valeurs de types différents est fortement typé et le contraire signifie faiblement typé.

Par conséquent, à un certain moment, j'ai senti poussé à croire que si une langue fournit un grand nombre de conversions automatiques ou de coercition entre les types (comme perl) peut être considéré comme faiblement typé, alors que d'autres langues qui fournissent seulement un peu de conversions peuvent être considérés comme fortement typé.

Je suis enclin à croire, cependant, que je dois être mal dans ce interepretation, je ne sais pas pourquoi ni comment l'expliquer.

Donc, mes questions sont les suivantes:

  • Ce que cela signifie vraiment pour qu'une langue soit vraiment faiblement typé?
  • Pouvez-vous citer des exemples de bonnes faiblement de frappe qui ne sont pas liées à la conversion automatique/automatique coercition fait par la langue?
  • Un langage peut-il être faiblement typé et fortement typé en même temps?

Merci d'avance pour toutes les références, les cas d'utilisation ou des exemples que vous fournissez et qui peut me conduire dans la bonne direction.

211voto

Eric Lippert Points 300275

Mise à JOUR: Cette question a été l'objet de mon blog le 15 octobre, 2012. Merci pour la grande question!


Ce que cela signifie vraiment pour qu'une langue soit "faiblement typé"?

Cela signifie que "cette langue utilise un système de type que je trouve de mauvais goût". Un "fortement typé" de la langue, par contraste, est une langue avec un système de type que je trouve agréable.

Les conditions sont essentiellement inutile, et vous devez les éviter. Wikipédia listes onze des significations différentes pour "fortement typé", plusieurs de qui sont contradictoires. Cela indique que les chances de confusion en cours de création sont élevés en toute conversation impliquant le terme "fortement typé" ou "faiblement typé".

Tout ce que vous pouvez vraiment dire avec certitude, c'est qu'un "fortement typé" la langue en cours de discussion a quelques restrictions supplémentaires dans le système de type, soit au moment de l'exécution ou de la compilation, que "faiblement typé" langue dans la discussion manque. Ce qui fait de cette restriction, peut-être ne peut pas être déterminé sans plus de contexte.

Au lieu d'utiliser "fortement typé" et "faiblement typé", vous devez décrire en détail ce genre de type de sécurité que vous voulez dire. Par exemple, le C# est un typé statiquement la langue et du type de coffre-fort de la langue et de la mémoire sûre de la langue, pour la plupart. C# permet à tous les trois de ces formes de "fort" à taper pour être violés. L'opérateur de cast viole le typage statique; il dit au compilateur "je sais plus sur le moteur d'exécution type de cette expression que vous faites". Si le développeur est fausse, alors l'exécution lèvera une exception afin de protéger la sécurité de type. Si le développeur souhaite le type de saut de la sécurité ou de la mémoire de la sécurité, ils peuvent le faire en désactivant le type de système de sécurité en faisant un "dangereux" bloquer. Dans un dangereux bloc, vous pouvez utiliser le pointeur de la magie pour traiter un int, un float (violation de la sécurité de type) ou d'écrire dans la mémoire vous ne possédez pas. (Violation de la mémoire de la sécurité.)

C# impose des restrictions de type qui sont contrôlés à la fois au moment de la compilation et à l'exécution, ce qui en fait une "fortement typé" de la langue par rapport à des langues qui ne moins au moment de la compilation de la vérification ou moins de contrôle d'exécution. C# permet également de vous dans des circonstances particulières faire pour contourner ces restrictions, faisant d'elle une "faiblement typé" de la langue par rapport à des langues qui ne vous permettent pas de faire une telle fin.

Qui est-il vraiment? Il est impossible de dire, cela dépend du point de vue de l'orateur et de leur attitude envers les différentes fonctions du langage.

64voto

Ilmari Karonen Points 20585

Comme d'autres l'ont noté, les termes "fortement typé" et "faiblement typé" ont donc de nombreuses significations différentes qu'il n'y a pas de réponse unique à votre question. Cependant, depuis que vous avez mentionné spécifiquement Perl dans votre question, permettez-moi d'essayer d'expliquer en quel sens Perl est faiblement typé.

Le point est que, en Perl, il n'y a pas une telle chose comme une "variable de type entier", une "variable de type float", une "variable de chaîne" ou une "variable booléenne". En fait, aussi loin que l'utilisateur peut (généralement) de dire, il n'y a même integer, float, string ou boolean valeurs: tout ce que vous avez sont "scalaires", qui sont toutes ces choses en même temps. Ainsi, vous pouvez, par exemple, écrire:

$foo = "123" + "456";           # $foo = 579
$bar = substr($foo, 2, 1);      # $bar = 9
$bar .= " lives";               # $bar = "9 lives"
$foo -= $bar;                   # $foo = 579 - 9 = 570

Bien sûr, comme vous l'avez remarque, tout cela peut être considéré comme un type de contrainte. Mais le point est que, en Perl, les types sont toujours contraints. En fait, il est assez difficile pour un utilisateur de savoir ce que l'interne "type" d'une variable peut être: à la ligne 2 dans mon exemple ci-dessus, en se demandant si la valeur de $bar est la chaîne de caractères "9" ou le nombre 9 est à peu près vide de sens, puisque, pour autant que Perl est concerné, ceux-ci sont la même chose. En effet, il est même possible pour un Perl scalaire à l'interne ont à la fois une chaîne de caractères et une valeur numérique dans le même temps, comme c'est par exemple le cas pour l' $foo , après la ligne 2 ci-dessus.

Le revers de tout cela est que, depuis Perl variables non typées (ou, plutôt, ne pas exposer leur type interne à l'utilisateur), les opérateurs ne peuvent pas être surchargés de faire des choses différentes pour les différents types d'arguments; vous ne pouvez pas simplement dire "cet opérateur ne X pour les nombres et Y pour cordes", parce que l'opérateur ne peut pas (ne pas) dire quel genre de valeurs de ses arguments.

Ainsi, par exemple, Perl a et les besoins à la fois numérique à l'opérateur d'addition (+) et un opérateur de concaténation de chaîne (.): comme vous l'avez vu ci-dessus, il est parfaitement bien pour ajouter des chaînes ("1" + "2" == "3") ou pour concaténer des nombres (1 . 2 == 12). De même, le numérique, les opérateurs de comparaison ==, !=, <, >, <=, >= et <=> comparer les valeurs numériques de leurs arguments, alors que la chaîne des opérateurs de comparaison eq, ne, lt, gt, le, ge et cmp de les comparer de manière lexicographique comme des chaînes de caractères. Donc, 2 < 10, mais 2 gt 10 (mais "02" lt 10, tandis que l' "02" == 2). (Vous l'esprit, certaines autres langues, comme le JavaScript, essayez d'adapter Perl-comme le typage faible, tandis que également faire de la surcharge d'opérateur. Cela conduit souvent à la laideur, comme la perte de l'associativité pour +.)

(La mouche dans la pommade ici, c'est que, pour des raisons historiques, Perl 5 n'ont que quelques cas particuliers, comme les opérateurs logiques bit à bit, dont le comportement dépend de la représentation interne de leurs arguments. Ceux-ci sont généralement considérées comme un ennuyeux défaut de conception, depuis la représentation interne peut changer pour le surprenant raisons, et ainsi de prédire la nature de ces opérateurs dans une situation donnée peut être délicat.)

Tout cela étant dit, on pourrait dire que Perl n' ont-fortes; ils sont tout simplement pas le genre de types que vous pourriez vous attendre. Plus précisément, en plus de la "scalaire" type discuté ci-dessus, Perl dispose également de deux types structurés: "array" et de "hachage". Ceux-ci sont très distinctes de scalaires, au point où Perl variables ont différents signes indiquant leur type ($ pour les scalaires, @ pour les tableaux, % pour le hachage)1. Il y sont des règles de contrainte entre ces types, de sorte que vous pouvez écrire par exemple, %foo = @bar, mais beaucoup d'entre eux sont tout à fait avec perte: par exemple, $foo = @bar affecte la longueur du tableau @bar de $foo, pas son contenu. (Aussi, il y a un peu étrange autres types, comme les typeglobs et I/O poignées, que vous ne verrez pas souvent exposés.)

Aussi, un léger point faible dans cette belle conception est l'existence de types de référence, qui sont un type spécial de scalaires (et qui peut être distingué de la normale scalaires, à l'aide de l' ref opérateur). Il est possible d'utiliser des références comme normal scalaires, mais leur chaîne/valeurs numériques ne sont pas particulièrement utiles, et ils ont tendance à perdre leur référence-ness si vous les modifiez à l'aide de la normale scalaire des opérations. Aussi, toute variable Perl2 peuvent être blessed à une classe, la transformant en un objet de cette classe; l'OO système de classe en Perl est un peu orthogonal au type primitif (ou typelessness) système décrit ci-dessus, même si c'est aussi "faible" dans le sens de la suite de la duck-typing paradigme. L'opinion générale est que, si vous trouvez vous-même la vérification de la classe d'un objet en Perl, vous êtes en train de faire quelque chose de mal.


1 en Fait, le sceau indique le type de la valeur en cours d'accès, de sorte que, par exemple, la première scalaire dans le tableau @foo est notée $foo[0]. Voir perlfaq4 pour plus de détails.

2 Objets en Perl sont (normalement) accessible par le biais de références, mais ce qui obtient réellement blessed est l' (éventuellement anonyme) variable de points de référence. Cependant, la bénédiction est en effet une propriété de la variable, pas de sa valeur, de sorte par exemple que l'affectation de la réelle béni variable à l'autre vous donne juste un peu profonde, sans être bénis copie de celui-ci. Voir perlobj pour plus de détails.

19voto

Konrad Rudolph Points 231505

En plus de ce qu'Eric a dit, considérez les points suivants du code C:

void f(void* x);

f(42);
f("hello");

Contrairement à des langages tels que Python, C#, Java ou autres joyeusetés, le ci-dessus est faiblement typé parce que nous perdons des informations de type. Eric a souligné à juste titre qu'en C# on peut contourner le compilateur par coulée, effectivement dire "j'en sais plus sur le type de cette variable que vous".

Mais même alors, le runtime toujours vérifier le type! Si le casting n'est pas valide, le système d'exécution de l'attraper et de lancer une exception.

Avec le type d'effacement, cela n'arrive pas de type d'information est jeté. Un casting d' void* C est exactement ce que fait. À cet égard, ci-dessus est fondamentalement différent d'un C# déclaration de la méthode comme void f(Object x).

(Techniquement, C# permet également le type d'effacement par le code unsafe ou de triage.)

C' est que faiblement typé qu'il obtient. Tout le reste est juste une question de statique vs dynamique de la vérification de type, c'est à dire du temps, quand un type est cochée.

15voto

SaulBack Points 611

Un parfait exemple est issu de l'article de wikipédia de Typage Fort:

Généralement taper fort implique que le langage de programmation des lieux de sévères restrictions sur le brassage qui est autorisé à se produire.

Le Typage Faible

a = 2
b = "2"

concatenate(a, b) # returns "22"
add(a, b) # returns 4

Typage Fort

a = 2
b = "2"

concatenate(a, b) # Type Error
add(a, b) # Type Error
concatenate(str(a), b) #Returns "22"
add(a, int(b)) # Returns 4

Notez qu'un typage faible de la langue peuvent mélanger les différents types sans erreurs. Un type fort de langue exige des types d'entrées pour les types. Dans un type fort la langue d'un type peut être converti (str(a) convertit un entier en une chaîne de caractères) ou de distribution (int(b)).

Cela dépend de l'interprétation de la dactylographie.

4voto

Edwin Dalorzo Points 19899

Je tiens à contribuer à la discussion avec mes propres recherches sur le sujet, comme d'autres, de commentaires et de contribuer, j'ai lu leurs réponses, et à la suite de leurs références et j'ai trouvé des informations intéressantes. Comme l'a suggéré, il est probable que la plupart de ce qui serait discuté dans le forum des Programmeurs, car il semble être plus théorique que pratique.

À partir d'un point de vue théorique, je pense que l'article de Luca Cardelli et Peter Wegner nommé Sur la Compréhension des Types, l'Abstraction de Données et le Polymorphisme est l'un des meilleurs arguments que j'ai lu.

Un type peut être considéré comme un ensemble de vêtements (ou un costume d'armure) protège sous-jacente d'un type de représentation de l'arbitraire ou utilisation non intentionnelle. Il fournit une couche protectrice qui cache la représentation sous-jacente et des contraintes de la façon dont les objets peuvent interagir avec d'autres objets. Dans un non système non typée objets sont nus dans la représentation sous-jacente est exposée aux yeux de tous. Violer le type de système consiste à retirer la protection ensemble de des vêtements et d'exploitation directement sur le nu de la représentation.

Cette déclaration semble suggérer que faiblement la frappe nous permettre d'accéder à la structure interne d'un type et de la manipuler comme si c'était quelque chose d'autre (un autre type). Peut-être ce que nous pourrions faire avec le code unsafe (mentionné par Eric) ou de type c-effacé pointeurs mentionné par Konrad.

L'article continue...

Langues dans lesquelles toutes les expressions sont de type uniforme sont appelés langages fortement typés. Si une langue est fortement typé de son compilateur peut garantir que les programmes qu'il accepte exécute sans type erreurs. En général, nous devons nous efforcer pour taper fort, et d'adopter le typage statique à chaque fois que possible. Notez que tous les statiquement typé la langue est fortement typé, mais l'inverse n'est pas nécessairement vrai.

En tant que tel, le typage fort, on entend l'absence d'erreurs de type, je ne peux que supposer que le typage faible signifie le contraire: la présence probable d'erreurs de type. Au moment de l'exécution ou de la compilation? Ne semble pas pertinent ici.

Drôle de chose, comme par cette définition, un langage puissant type de contraintes comme Perl serait considéré comme fortement typé, parce que le système n'est pas un échec, mais c'est de traiter avec des types en contraignant eux appropriées et bien définies, les équivalences.

D'autre part, pourrais-je dire que l'allocation d' ClassCastException et ArrayStoreException (en Java) et InvalidCastException, ArrayTypeMismatchException (en C#) indique un niveau de faiblement à taper, au moins au moment de la compilation? Eric réponse semble d'accord avec cela.

Dans un second article, nommé Typeful de Programmation fournie dans l'une des références fournies dans l'une des réponses à cette question, Luca Cardelli, approfondit la notion de type d'infractions:

La plupart des langages de programmation permettent de type arbitraire violations, certains sans discernement, certains ne restreint les parties d'un programme. Les opérations qui impliquent type de violations sont appelés malsain. Type les violations de l'automne dans plusieurs classes [parmi lesquels nous pouvons citer]:

De base-valeur de contraintes: celles-ci incluent les conversions entre nombres entiers, les booléens, les personnages, les décors, etc. Il n'est pas nécessaire pour le type de violations ici, parce que construit-dans les interfaces peuvent être fournis pour mener à bien la forçages dans un type de sons.

En tant que tel, forçages de type tels que ceux fournis par les opérateurs pourrait être considéré comme le type de violations, mais à moins qu'ils briser la cohérence du système de type, on peut dire qu'elles ne conduisent pas à un faiblement typé système.

Sur cette base ni Python, Perl, Java ou C# sont faiblement typé.

Cardelli mentionne deux type vilations que j'ai très bien envisager le cas de la véritable faiblesse de frappe:

Adresse de l'arithmétique. Si nécessaire, il devrait y être intégré (malsain) de l'interface, en fournissant la opérations sur les adresses et les conversions de type. Diverses situations impliquent les pointeurs dans le tas (très dangereux à la relocalisation des collectionneurs), des pointeurs vers les pile, des pointeurs vers des zones statiques, et des pointeurs vers d'autres adresses des espaces. Parfois, tableau d'indexation peut remplacer l'adresse de l'arithmétique. Mappage de la mémoire. Il s'agit d'examiner une zone de la mémoire comme un non structurées tableau, bien qu'il contient des données structurées. C'est typique des allocateurs de mémoire et de collectionneurs.

Ce genre de choses possible dans des langages tels que C (mentionné par Konrad) ou par le code unsafe .Net (mentionné par Eric) serait vraiment implique faiblement à taper.

Je crois que la meilleure réponse à ce jour est Eric, parce que la définition de ces concepts est très théorique, et quand il s'agit d'une langue en particulier, l'interprétation de tous ces concepts peuvent conduire à différentes conclusions discutables.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X