Les langages typés dynamiquement que je connais ne permettent jamais aux développeurs de spécifier les types de variables, ou du moins ont un support très limité pour cela.
JavaScript, par exemple, ne fournit aucun mécanisme pour appliquer les types de variables lorsque cela est pratique. PHP vous permet de spécifier certains types d'arguments de méthode, mais il n'y a aucun moyen d'utiliser les types natifs ( int
, string
, etc.) pour les arguments, et il n'y a pas moyen de faire respecter les types pour autre chose que des arguments.
Dans le même temps, il serait pratique d'avoir le choix de spécifier dans certains cas le type d'une variable dans un langage typé dynamiquement, au lieu de faire la vérification de type manuellement.
Pourquoi existe-t-il une telle limitation? Est-ce pour des raisons techniques / de performances (je suppose que c'est dans le cas de JavaScript), ou uniquement pour des raisons politiques (ce qui est, je crois, le cas de PHP)? Est-ce un cas pour d'autres langues typées dynamiquement que je ne connais pas?
Edit: en suivant les réponses et les commentaires, voici un exemple de clarification: disons que nous avons la méthode suivante en PHP simple:
public function CreateProduct($name, $description, $price, $quantity)
{
// Check the arguments.
if (!is_string($name)) throw new Exception('The name argument is expected to be a string.');
if (!is_string($description)) throw new Exception('The description argument is expected to be a string.');
if (!is_float($price) || is_double($price)) throw new Exception('The price argument is expected to be a float or a double.');
if (!is_int($quantity)) throw new Exception('The quantity argument is expected to be an integer.');
if (!$name) throw new Exception('The name argument cannot be an empty string.');
if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
if ($price < 0) throw new Exception('The price argument cannot be less than zero.');
// We can finally begin to write the actual code.
// TODO: Implement the method here.
}
Avec quelques efforts, cela peut être réécrit comme (voir aussi Programmation par contrats en PHP ):
public function CreateProduct($name, $description, $price, $quantity)
{
Component::CheckArguments(__FILE__, __LINE__, array(
'name' => array('value' => $name, 'type' => VTYPE_STRING),
'description' => array('value' => $description, 'type' => VTYPE_STRING),
'price' => array('value' => $price, 'type' => VTYPE_FLOAT_OR_DOUBLE),
'quantity' => array('value' => $quantity, 'type' => VTYPE_INT)
));
if (!$name) throw new Exception('The name argument cannot be an empty string.');
if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
if ($price < 0) throw new Exception('The price argument cannot be less than zero.');
// We can finally begin to write the actual code.
// TODO: Implement the method here.
}
Mais la même méthode serait écrite comme suit si PHP acceptait éventuellement des types natifs pour les arguments:
public function CreateProduct(string $name, string $description, double $price, int $quantity)
{
// Check the arguments.
if (!$name) throw new Exception('The name argument cannot be an empty string.');
if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
if ($price < 0) throw new Exception('The price argument cannot be less than zero.');
// We can finally begin to write the actual code.
// TODO: Implement the method here.
}
Lequel est le plus court à écrire? Lequel est le plus facile à lire?
la source
Réponses:
Le point d'avoir un typage statique est la capacité de prouver statiquement que votre programme est correct en ce qui concerne les types (note: pas complètement correct dans tous les sens). Si vous disposez d'un système de type statique, vous pouvez détecter la plupart du temps des erreurs de type.
Si vous ne disposez que d'informations de type partielles, vous ne pouvez vérifier que les petits morceaux d'un graphique d'appel où les informations de type sont complètes. Mais vous avez passé du temps et des efforts à spécifier des informations de type pour les pièces incomplètes, où cela ne peut pas vous aider mais pourrait donner un faux sentiment de sécurité.
Pour exprimer des informations de type, vous avez besoin d'une partie du langage qui ne peut pas être excessivement simple. Bientôt, vous découvrirez que des informations comme
int
ne suffisent pas; vous voudrez quelque chose commeList<Pair<Int, String>>
, puis des types paramétriques, etc. Cela peut être assez déroutant même dans le cas assez simple de Java.Ensuite, vous devrez gérer ces informations pendant la phase de traduction et la phase d'exécution, car il est idiot de ne vérifier que les erreurs statiques; l'utilisateur va s'attendre à ce que les contraintes de type tiennent toujours si elles sont spécifiées. Les langages dynamiques ne sont pas trop rapides comme ils le sont, et de tels contrôles ralentiront encore plus les performances. Un langage statique peut demander beaucoup d'efforts pour vérifier les types car il ne le fait qu'une seule fois; une langue dynamique ne peut pas.
Imaginez maintenant que vous ajoutiez et mainteniez tout cela afin que les gens utilisent parfois ces fonctionnalités en option , ne détectant qu'une petite fraction des erreurs de type. Je ne pense pas que cela en vaille la peine.
L'intérêt des langages dynamiques est d'avoir un cadre très petit et très malléable, dans lequel vous pouvez facilement faire des choses qui sont beaucoup plus impliquées quand elles sont faites dans un langage statique: diverses formes de patch de singe qui sont utilisées pour la métaprogrammation, la simulation et tests, remplacement dynamique de code, etc. Smalltalk et Lisp, tous deux très dynamiques, l'ont poussé à l'extrême au point d'envoyer des images d'environnement au lieu de construire à partir de la source. Mais lorsque vous voulez vous assurer que des chemins de données particuliers sont de type sécurisé, ajoutez des assertions et écrivez d'autres tests unitaires.
la source
Dans la plupart des langages dynamiques, vous pouvez au moins tester dynamiquement le type d'un objet ou d'une valeur.
Et il existe des inférenceurs de type statique, des vérificateurs et / ou des exécuteurs pour certains langages dynamiques: par exemple
Et Perl 6 prendra en charge un système de type optionnel avec une saisie statique.
Mais je suppose que l'essentiel est que beaucoup de gens utilisent des langages dynamiquement parce qu'ils sont typés dynamiquement, et pour eux le typage statique optionnel est très "ho hum". Et beaucoup d'autres personnes les utilisent parce qu'elles sont "faciles à utiliser pour les non-programmeurs", en grande partie en raison de la typographie dynamique de nature indulgente. Pour eux, la saisie facultative est quelque chose qu'ils ne comprendront pas ou ne seront pas gênés d'utiliser.
Si vous étiez cynique, vous pourriez dire que la saisie statique facultative offre le pire des deux mondes. Pour un fanatique de type statique, cela n'empêche pas toutes les défaillances de type dynamique. Pour un fan de type dynamique, c'est toujours une veste droite ... quoique avec les bretelles pas bien serrées.
la source
Javascript prévoyait d'inclure un typage statique facultatif, et il semble que de nombreuses langues dynamiques matures se dirigent dans cette direction-
La raison en est que lorsque vous codez pour la première fois, vous voulez être saisi rapidement et dynamiquement. Une fois que votre code est solide, fonctionne et a de nombreux usages, vous souhaitez verrouiller la conception pour réduire les erreurs. (cela est avantageux pour les utilisateurs et les développeurs, car les premiers obtiendront une vérification d'erreur sur leurs appels et les seconds ne casseront pas les choses accidentellement.
Cela a du sens pour moi, car je trouve généralement trop de vérification de type au début d'un projet, trop peu à la fin de sa durée de vie, quelle que soit la langue que j'utilise;).
la source
Objets Python faire ont un type.
Vous spécifiez le type lorsque vous créez l'objet.
En fait, une vérification de type manuelle en Python est presque toujours une perte de temps et de code.
C'est simplement une mauvaise pratique d'écrire du code de vérification de type en Python.
Si un type inapproprié a été utilisé par un sociopathe malveillant, les méthodes ordinaires de Python lèveront une exception ordinaire lorsque le type ne convient pas.
Vous n'écrivez aucun code, votre programme échoue toujours avec un
TypeError
.Il existe de très rares cas où vous devez déterminer le type au moment de l'exécution.
Puisqu'il ne s'agit pas d'une "limitation", la question n'est pas une vraie question.
la source
La plupart du temps, vous n'en avez pas besoin, du moins pas au niveau de détail que vous proposez. En PHP, les opérateurs que vous utilisez indiquent parfaitement ce que vous attendez des arguments; c'est un peu une erreur de conception bien que PHP convertisse vos valeurs si possible, même lorsque vous passez un tableau à une opération qui attend une chaîne, et parce que la conversion n'est pas toujours significative, vous obtenez parfois des résultats étranges ( et c'est exactement là que les vérifications de type sont utiles). En dehors de cela, peu importe si vous ajoutez des entiers
1
et5
ou des chaînes"1"
et"5"
- le simple fait que vous utilisez le+
L'opérateur signale à PHP que vous voulez traiter les arguments comme des nombres, et PHP obéira. Une situation intéressante est lorsque vous recevez des résultats de requête de MySQL: de nombreuses valeurs numériques sont simplement renvoyées sous forme de chaînes, mais vous ne le remarquerez pas car PHP les convertit pour vous chaque fois que vous les traitez comme des nombres.Python est un peu plus strict sur ses types, mais contrairement à PHP, Python a eu des exceptions depuis le début et l'utilise de manière cohérente. Le paradigme «plus facile de demander pardon que permission» suggère d'effectuer simplement l'opération sans vérification de type, et de compter sur une exception levée lorsque les types n'ont pas de sens. Le seul inconvénient auquel je peux penser, c'est que parfois, vous constaterez que quelque part un type ne correspond pas à ce que vous attendez, mais trouver la raison peut être fastidieux.
Et il y a une autre raison à considérer: les langages dynamiques n'ont pas d' étape de compilation. Même si vous avez des contraintes de type, elles ne peuvent se déclencher qu'au moment de l'exécution, simplement parce qu'il n'y a pas de temps de compilation . Si vos vérifications entraînent de toute façon des erreurs d'exécution, il est beaucoup plus facile de les modéliser en conséquence: sous forme de vérifications explicites (comme
is_XXX()
en PHP outypeof
en javascript), ou en lançant des exceptions (comme Python). Fonctionnellement, vous avez le même effet (une erreur est signalée au moment de l'exécution lorsqu'un contrôle de type échoue), mais il s'intègre mieux avec le reste de la sémantique du langage. Il n'est tout simplement pas logique de traiter les erreurs de type fondamentalement différentes des autres erreurs d'exécution dans un langage dynamique.la source
Vous pouvez être intéressé par Haskell - son système de types déduit les types du code, et vous pouvez également spécifier des types.
la source
Comme les autres réponses ont fait allusion, il existe deux approches pour taper lors de l'implémentation d'un langage de programmation.
Les deux approches sont valides et celles à utiliser dépendent en partie de considérations techniques comme les performances et en partie de raisons politiques comme le marché cible de la langue.
la source
Tout d'abord, des langages dynamiques ont été créés principalement pour la facilité d'utilisation. Comme vous l'avez mentionné, il est vraiment bon de prendre la conversion de type automatiquement et de nous fournir moins de frais généraux. Mais en même temps, il manque de problèmes de performances.
Vous pouvez vous en tenir aux langages dynamiques, au cas où vous ne vous souciez pas des performances. Supposons, par exemple, que JavaScript s'exécute plus lentement lorsqu'il doit effectuer plusieurs conversions de types dans votre programme, mais cela aide à réduire le nombre de lignes dans votre code.
Et pour être mentionné, il existe même d'autres langages dynamiques qui permettent au programmeur de spécifier le type. Par exemple Groovy est l'un des fameux langages dynamiques qui s'exécutent sur JVM. Et il est même devenu très célèbre ces derniers jours. Notez que les performances de Groovy sont identiques à celles de Java.
J'espère que cela vous aide.
la source
Cela n'a tout simplement aucun sens.
Pourquoi?
Parce que le système de types de DTL est précisément tel que les types ne peuvent pas être déterminés au moment de la compilation. Par conséquent, le compilateur n'a même pas pu vérifier que le type spécifié aurait du sens.
la source
Jetez un œil à Go, en surface, il est typé statiquement, mais ces types peuvent être des interfaces qui sont essentiellement dynamiques.
la source