Quelle est la plus grande faille de conception que vous ayez rencontrée dans un langage de programmation? [fermé]


29

Tous les langages de programmation ont leurs défauts de conception simplement parce qu’aucun langage ne peut être parfait, tout comme la plupart (toutes?) D’autres choses. Cela mis à part, quel défaut de conception dans un langage de programmation vous a le plus ennuyé tout au long de votre histoire de programmeur?

Notez que si une langue est "mauvaise" simplement parce qu'elle n'est pas conçue pour une chose spécifique, ce n'est pas un défaut de conception, mais une caractéristique de la conception, alors ne listez pas ces ennuis de langues. Si une langue ne convient pas à ce pour quoi elle est conçue, c'est bien sûr un défaut de conception. Les choses spécifiques à la mise en œuvre et les choses sous le capot ne comptent pas non plus.


6
Notez que cela est constructif pour les concepteurs de langage (erreurs à éviter), si quelqu'un souhaite se demander à quel point cette question est constructive.
Anto

Dupe

1
@greyfade: Pas vraiment, il s'agit de défauts dans la langue réelle, qui semblent concerner des choses qui réduisent l'adoption d'une langue, ce qui pourrait inclure une mauvaise bibliothèque standard ou tout simplement un mauvais site Web pour la langue. Certaines réponses listent par exemple une mauvaise syntaxe, mais ce n'est pas un défaut de conception spécifique
Anto

8
Le plus gros défaut de tout langage de programmation? Humains.
Joel Etherton

Si ces réponses sont les plus gros défauts, alors je suis vraiment impressionné par les langages de programmation.
Tom Hawtin - tackline

Réponses:


42

Un de mes gros ennuis est la façon dont les switchcas dans les langages dérivés de C passent par défaut au cas suivant si vous oubliez de les utiliser break. Je comprends que cela est utile dans le code de très bas niveau (par exemple, le périphérique de Duff ), mais il est généralement inapproprié pour le code de niveau application et est une source courante d'erreurs de codage.

Je me souviens vers 1995, lorsque je lisais pour la première fois les détails de Java, lorsque je suis arrivé à la partie concernant la switchdéclaration, j'étais très déçu qu'ils aient conservé le comportement de repli par défaut. Cela fait juste switchun glorifié gotoavec un autre nom.


3
@Christopher Mahan: switchne doit pas fonctionner de cette façon. Par exemple, l' instruction case / when d' Ada (équivalente à switch / case) n'a pas de comportement d'interruption.
Greg Hewgill

2
@Greg: les switchinstructions similaires à des langages non liés à C ne doivent pas fonctionner de cette façon. Mais si vous utilisez le flux de contrôle de type C ( {... }, for (i = 0; i < N; ++i), return, etc.), l' inférence linguistique va rendre les gens attendent switchà travailler comme C, et en lui donnant Ada / Pascal / BASIC sémantique aurait des gens confus. C # requiert breakdans les switchinstructions pour la même raison, bien qu'il le rend moins sujet aux erreurs en interdisant les retombées silencieuses. (Mais j'aurais aimé que tu fall;goto case
puisses

4
alors n'écrivez pas switch, écrivez if () else. la raison pour laquelle vous vous plaignez est ce qui rend le changement meilleur: ce n'est pas un conditionnel vrai / faux, c'est un conditionnel numérique, et cela le rend différent. Vous pouvez également écrire votre propre fonction de commutateur.
jokoon

9
-1 Je considère que c'est un avantage de laisser tomber, il n'y a pas d'autre danger que la bêtise, mais il accorde une fonction supplémentaire.
Orbling

11
Le problème n'est pas que cela switch permette la chute. C'est que la plupart des utilisations de fallthrough ne sont pas intentionnelles.
dan04

41

Je n'ai jamais vraiment aimé l'utilisation de =pour l'affectation et ==pour les tests d'égalité dans les langages dérivés C. Le risque de confusion et d'erreurs est trop élevé. Et ne me lancez même pas sur ===Javascript.

Mieux aurait été :=pour les affectations et =les tests d'égalité. La sémantique aurait pu être exactement la même qu'aujourd'hui, où l'affectation est une expression qui produit également une valeur.


3
@Nemanja Trifunovic: J'ai d'abord pensé à cette suggestion, mais elle a une ambiguïté malheureuse en C avec une comparaison inférieure à un nombre négatif (c.-à-d. x<-5). Les programmeurs C ne toléreraient pas ce genre d'espace blanc requis :)
Greg Hewgill

7
@Greg: Je préférerais :=et ==parce qu'il serait trop facile d'oublier le :et de ne pas être averti comme c'est déjà le cas (bien qu'inversé) lorsque vous oubliez un =aujourd'hui. Je suis reconnaissant pour les avertissements du compilateur à ce sujet ...
Matthieu M.

13
Sur presque tous les claviers que j'ai jamais utilisés, ": =" nécessite de changer la touche Maj tout en la tapant. Sur celui que j'utilise maintenant, «:» est en majuscules et «=» est en minuscules, et je l'ai inversé. Je tape beaucoup de devoirs et je n'ai pas besoin de ce genre de tracas de frappe.
David Thornley

14
@David Thornley: Le code est lu beaucoup plus de fois qu'il n'est écrit. Je n'achète aucun argument à propos de "taper des tracas".
Greg Hewgill

8
@Greg Hewgill: Bien sûr, il est lu plus souvent qu'écrit. Cependant, le problème entre =et ==n'est pas en lecture, car ce sont des symboles distincts. C'est par écrit et s'assurer que vous avez le bon.
David Thornley

29

Le choix de +Javascript pour l' addition et la concaténation de chaînes a été une terrible erreur. Étant donné que les valeurs ne sont pas typées, cela conduit à des règles byzantines qui déterminent s'il faut +ajouter ou concaténer, selon le contenu exact de chaque opérande.

Il aurait été facile au début d'introduire un opérateur complètement nouveau comme $pour la concaténation de chaînes.


13
@Barry: Pas vraiment. +a beaucoup de sens en tant qu'opérateur de concaténation de chaînes dans un langage fortement typé. Le problème est que Javascript l'utilise mais n'est pas fortement typé.
Mason Wheeler

13
@Mason: +n'a pas de sens pour la concaténation, car la concaténation n'est certainement pas commutative. C'est un abus en ce qui me concerne.
Matthieu M.

12
@Matthieu: Umm ... pourquoi est-ce important? La concaténation n'est pas commutative (comme l'addition l'est), mais l'ajout de deux chaînes est absurde, donc personne n'y pense de cette façon. Vous inventez un problème là où il n'en existe pas.
Mason Wheeler

4
il suffit de passer en C ++ et d'ajouter tout type de surcharge ésotérique à l'opérateur de votre choix
Newtopian

8
@Matthieu: La commutativité n'est pas le problème ici. Si JS avait une classe Matrix, considéreriez-vous comme un abus le fait d'avoir un *opérateur?
dan04

24

Je trouve que Javascript par défaut est global à un problème majeur, et souvent source de bugs si vous n'utilisez pas JSLint ou similaire


2
Par défaut à global? Je suis content de ne pas utiliser JS alors ...
Anto

5
En fait, c'est un langage très agréable, avec quelques mauvais choix de conception. Ceci est le principal, si vous ne définissez pas une variable, elle le définira comme un global. La bonne chose est qu'en utilisant le programme Jslint de Doug Crockford, vous pouvez attraper cette erreur et bien plus encore.
Zachary K

1
Utilisez simplement varchaque fois que vous déclarez une variable et vous êtes prêt à partir. Et ne me dites pas que c'est trop de frappe car Java vous oblige à déclarer tous les types deux fois et personne ne se plaint que ce soit un choix de conception merdique.
davidk01

3
@ davidk01: Les gens s'en plaignent. De même, les gens se sont plaints d'avoir à déclarer std::map<KEY, VALUE>::const_iteratorsuffisamment de variables en C ++ qui autosont ajoutées à ce langage.
dan04

1
la "use strict"directive, ajoutée dans es5, transforme les références non déclarées en erreur.
Sean McMillan

22

Le préprocesseur en C et C ++ est un kludge massif, crée des abstractions qui fuient comme des tamis, encourage le code spaghetti via les nids de #ifdefdéclarations de rat , et nécessite des ALL_CAPSnoms horriblement illisibles pour contourner ses limites. La racine de ces problèmes est qu'elle opère au niveau textuel plutôt qu'au niveau syntaxique ou sémantique. Il aurait dû être remplacé par de véritables fonctionnalités de langage pour ses différents cas d'utilisation. Voici quelques exemples, bien que certains d'entre eux soient résolus en C ++, C99 ou dans des extensions standard non officielles mais de facto :

  • #include aurait dû être remplacé par un véritable système de modules.

  • Les fonctions en ligne et les modèles / génériques pourraient remplacer la plupart des cas d'utilisation des appels de fonction.

  • Une sorte de caractéristique de constante de temps manifeste / compilé pourrait être utilisée pour déclarer de telles constantes. Les extensions d'enum de D fonctionnent très bien ici.

  • De vraies macros au niveau de l'arbre de syntaxe pourraient résoudre de nombreux cas d'utilisation divers.

  • Des mixins de chaînes peuvent être utilisés pour le cas d'utilisation de l'injection de code.

  • static ifou des versioninstructions peuvent être utilisées pour la compilation conditionnelle.


2
@dsimcha: Je suis d'accord avec le #includeproblème, mais le système de modules a été inventé ... après! Et C et C ++ visent un maximum de rétrocompatibilité: /
Matthieu M.

@Matthieu: Oui, les systèmes de modules ont été inventés par la suite, mais nous parlons ici de recul.
dsimcha

3
Je suis d'accord que c'est une douleur énorme dans diverses parties du corps, mais la conception multi-passes a l'avantage de la simplicité: un compilateur C n'a pas besoin d'en savoir beaucoup sur le contexte de fonctionnement avant de pouvoir compiler avec succès un morceau de code C . Cela ne peut être qualifié d'erreur de conception que si vous pouvez montrer que les coûts d'utilisation d'un système de modules hypothétique dans le langage C lui-même (par exemple, les classes de type C ++) sont toujours inférieurs ou comparables au #includepiratage basé sur cpp actuel .
reinierpost

Je suis d'accord. Cependant, mais certaines personnes pensent que le prétraitement est une bonne chose et se plaignent qu'il n'est pas pris en charge par (par exemple) Java.
Stephen C

5
@Stephen: Je suis d'accord que Java avec un préprocesseur pourrait être meilleur que Java sans, mais seulement parce que Java n'a pas plusieurs des "vraies" fonctionnalités nécessaires pour remplacer le préprocesseur. Dans des langages comme D, qui incluent de telles fonctionnalités et Python, qui obtient de la flexibilité par d'autres moyens en étant dynamique, je ne le manque pas du tout.
dsimcha

21

On pourrait énumérer des centaines d'erreurs dans des centaines de langues, mais l'OMI n'est pas un exercice utile du point de vue de la conception d'une langue.

Pourquoi?

Parce que quelque chose qui serait une erreur dans une langue ne serait pas une erreur dans une autre langue. Par exemple:

  • Faire de C un langage géré (c'est-à-dire ramassé) ou restreindre les types primitifs limiterait son utilité en tant que langage semi-portable de bas niveau.
  • L'ajout de la gestion de la mémoire de style C à Java (par exemple, pour résoudre des problèmes de performances) le romprait.

Il y a des leçons à tirer, mais les leçons sont rarement claires, et pour les comprendre, vous devez comprendre les compromis techniques ... et le contexte historique. (Par exemple, l'implémentation lourde de Java des génériques est la conséquence d'une exigence commerciale primordiale pour maintenir la compatibilité descendante.)

OMI, si vous êtes sérieux au sujet de la conception d'une nouvelle langue, vous devez réellement utiliser un large éventail de langues existantes (et étudier les langues historiques) ... et vous faire votre propre idée des erreurs. Et vous devez garder à l'esprit que chacune de ces langues a été conçue dans un contexte historique particulier, pour répondre à un besoin particulier.

S'il y a des leçons générales à tirer, elles sont au niveau "méta":

  • Vous ne pouvez pas concevoir un langage de programmation idéal à toutes fins.
  • Vous ne pouvez pas éviter de faire des erreurs ... surtout quand on le regarde avec le recul.
  • De nombreuses erreurs sont difficiles à corriger ... pour les utilisateurs de votre langue.
  • Vous devez tenir compte des antécédents et des compétences de votre public cible; c'est-à-dire les programmeurs existants.
  • Vous ne pouvez pas satisfaire tout le monde.

9
-1 - les langages de programmation suivent les objectifs de conception. Une des caractéristiques d'un langage qui va à l'encontre de ces objectifs est un défaut de conception, sauf s'il s'agit d'un compromis nécessaire pour l'un de ses autres objectifs. Peu de langues sont faites dans le but de satisfaire tout le monde, mais toutes les langues devraient essayer de satisfaire les personnes qu'elle entend satisfaire en premier lieu. Ce genre de rectitude politique postmoderniste est assez étouffant pour la recherche et le développement de langages de programmation.
Rei Miyasaka

Mon point est qu'il est difficile de tirer des leçons sans tenir compte des objectifs de conception.
Stephen C

1
il me semble que le PO a déjà expliqué votre réponse dans le deuxième paragraphe de la question.
Aidan Cully

20

C et C ++ : tous ces types entiers qui ne veulent rien dire .

Surtout char. Est-ce du texte ou un minuscule entier? S'il s'agit de texte, s'agit-il d'un caractère "ANSI" ou d'une unité de code UTF-8? S'il s'agit d'un entier, est-il signé ou non signé?

int était censé être l'entier de taille "native", mais sur les systèmes 64 bits, il ne l'est pas.

longpeut ou peut ne pas être plus grand que int. Il peut ou non avoir la taille d'un pointeur. C'est à peu près une décision arbitraire de la part des rédacteurs du compilateur, que ce soit en 32 bits ou en 64 bits.

Certainement une langue des années 1970. Avant Unicode. Avant les ordinateurs 64 bits.


10
C n'a pas été conçu pour être un langage standard, il ne peut donc pas s'agir d'une erreur de conception. Il a été conçu pour modéliser un processeur en tant qu'assembleur portable en évitant le code assembleur spécifique au processeur. Cependant, il a été corrigé en Java.

7
Je pense que le plus gros problème, ce sont les nouvelles langues qui continuent à utiliser les mêmes termes dénués de sens, bien que l'histoire nous montre que c'est une idée terrible. Au moins, les gars C ont remarqué leur erreur et ont créé des types int standard.
Mark H

5
Un char n'est pas une unité utf-8. Un caractère utf-8 peut prendre plus de 8 bits à stocker. C n'est pas un langage des années 1970, je l'utilise maintenant (volontairement) pour un projet.
dan_waterworth

4
C n'est guère plus qu'une abstraction de haut niveau du processeur PDP-11. Par exemple, la pré et l'incrémentation ont été directement prises en charge par le PDP-11.
bit-twiddler

5
C'est une réponse terriblement erronée. Tout d'abord, C et C ++ ne sont pas interchangeables. Deuxièmement, la spécification de langage définit clairement ce qu'est un char - Un objet déclaré comme type char est suffisamment grand pour stocker n'importe quel membre du jeu de caractères d'exécution de base. . Troisièmement, C n'est pas un "langage des années 70", c'est un langage qui vit à proximité du matériel et est probablement le langage qui permet finalement à toutes vos abstractions de haut niveau d'avoir un sens pour un CPU. Vous vous démarquez en tant que personne qui ne connaît que des langues de haut niveau et n'a aucune appréciation du fonctionnement réel des choses. -1
Ed S.

18

null.

Son inventeur, Tony Hoare, l'appelle "l'erreur du milliard de dollars" .

Il a été introduit dans ALGOL dans les années 60 et existe aujourd'hui dans la plupart des langages de programmation couramment utilisés.

La meilleure alternative, utilisée dans des langages comme OCaml et Haskell, est peut - être . L'idée générale est que les références d'objet ne peuvent pas être nulles / vides / inexistantes à moins qu'il y ait une indication explicite qu'elles peuvent l'être.

(Bien que Tony soit génial dans sa modestie, je pense que presque n'importe qui aurait fait la même erreur, et il s'est avéré être le premier.)


Pas d'accord, même avec son inventeur !!! null est la valeur vide pour le type de données pointeur / référence. Strings a une chaîne vide, sets a un ensemble vide (Pascal empty set = []), les entiers ont 0. La plupart des langages de programmation qui utilisent null / nil / peu importe, si une variable est affectée correctement, une erreur nulle peut être évitée.
umlcat

4
@ user14579: Chaque langue qui prend en charge tout type de jeu, de chaîne ou de tableau possède {}, mais celle-ci est toujours sémantiquement appropriée et ne se bloquera pas sauf si vous avez déjà quelque chose qui pourrait éventuellement provoquer une erreur de limites de tableau - mais c'est un autre problème. Vous pouvez traiter une chaîne vide pour mettre en majuscule tous les caractères, ce qui entraînera une chaîne vide. Vous essayez la même chose sur une chaîne nulle, et sans considération, cela va planter. Le problème est que cette considération appropriée est fastidieuse, souvent oubliée, et rend difficile l'écriture de fonctions à expression simple (ie lambdas).
Rei Miyasaka

1
Je gagne de l'argent à chaque fois que je tape null ... oh oui, quelqu'un perd de l'argent à chaque fois que je tape null. Sauf cette fois.
kevpie

3
@umlcat - lorsque vous avez des langues avec des correspondances de motifs comme Ocaml, Haskell et F #, en utilisant la fonction Maybe x | Aucun modèle ne vous empêche d'oublier la casse nulle au moment de la compilation. Aucune ruse de compilation ne peut détecter une erreur dans les langues où null est l'idiome établi. Puisque vous devez explicitement choisir de ne pas traiter le cas nul dans les langues qui ont la monade Maybe et Some, ils ont un sérieux avantage sur l'approche "null".
JasonTrue

1
@Jason - J'aime à penser maybecomme un opt-in nul, alors que l'exception nulle est un opt-out. Bien sûr, il y a certaines choses à dire sur la différence entre les erreurs d'exécution et les erreurs de compilation, mais le fait que null soit essentiellement un comportement d'injection est remarquable en soi.
Rei Miyasaka

14

J'ai l'impression que les gens qui ont conçu PHP n'ont pas utilisé de clavier normal, ils n'utilisent même pas de clavier colemak, car ils auraient dû réaliser ce qu'ils faisaient.

Je suis développeur PHP. PHP n'est pas amusant à taper.

Who::in::their::right::mind::would::do::this()? L' ::opérateur doit maintenir la touche Maj enfoncée, puis appuyer sur deux touches. Quel gaspillage d'énergie.

Bien que-> ce-> soit-> pas-> beaucoup-> mieux. Cela nécessite également trois pressions sur les touches, le décalage étant entre les deux symboles.

$last = $we.$have.$the.$dumb.'$'.$character. Le signe dollar est utilisé énormément de fois et nécessite l'étirement de la récompense jusqu'au sommet du clavier plus une pression sur la touche Maj.

Pourquoi n'ont-ils pas pu concevoir PHP pour utiliser des clés beaucoup plus rapides à taper? Pourquoi ne pouvait-on pas we.do.this()ou faire démarrer vars avec une clé qui ne nécessite qu'une seule pression sur une touche - ou pas du tout (JavaScript) et juste prédéfinir tous les vars (comme je dois quand même le faire pour E_STRICT)!

Je ne suis pas une dactylo lente - mais ce n'est qu'un choix de conception boiteux.


Perl partage cette douleur.
Daenyth

2
Il en va de même pour C ++, et pour une raison bizarre inexplicable, PowerShell.
Rei Miyasaka

2
Utilisez un éditeur plus puissant et définissez vos propres séquences de touches pour ces opérateurs.
kevin cline

1
I::have::nothing::against::this->at.all()
Mateen Ulhaq

1
Peut-être qu'ils n'utilisent pas les claviers qwerty. $ et: pas besoin d'appuyer sur la touche Maj sur tous les azerty comme les claviers.
Arkh

13

L'utilisation de formulaires inspirés du bureau dans asp.net .

Il a toujours ressenti un fudge et a gêné la façon dont le Web fonctionne réellement. Heureusement, asp.net-mvc ne souffre pas de la même manière, mais avec le mérite de Ruby, etc. pour cette inspiration.


18
N'est-ce pas un truc de bibliothèque?
nikie

@nikie c'est un bon point;)
plongé

1
@nikie En fait, le code ASPX basé sur XML est un langage, vous pouvez donc le tordre pour qu'il fonctionne. : D
CodexArcanum

2
Le vrai problème avec ASP.NET, je pense, est à quel point il essaie de cacher les détails du Web au programmeur. Il y a en fait des choses vraiment soignées et utiles dans ASP.NET, mais vous devez vous battre si dur et creuser si profondément pour y arriver.
CodexArcanum

1
D'un autre côté, il existe des milliers et des milliers d'applications de collecte de données simples et réussies qui sont assemblées à l'aide de l'application de bureau "classique". La seule mauvaise chose était que jusqu'à MVC, la seule option Microsoft était les formulaires Windows.
ElGringoGrande

13

Pour moi, c'est le manque absolu de PHP de conventions de nommage et de classement des arguments dans sa bibliothèque standard.

Bien que la nécessité pour JASS d'annuler les références après la libération / suppression de l'objet référencé (ou que la référence fuit et que plusieurs octets de mémoire soient perdus) est plus sérieuse, mais comme JASS est un langage à usage unique, il n'est pas si critique.


9
L'absence de conventions dans stdlib de PHP n'est sans doute pas un défaut de conception de langage .

3
@delnan: L'absence de conventions est le résultat de la façon dont PHP a été conçu, et a donc beaucoup à voir avec la conception du langage. De plus, il n'est pas clair pour moi qu'il existe une distinction claire entre les bibliothèques et la langue. Lisp en particulier a une fière tradition d'amorcer une langue par dessus une autre.
btilly

1
La chose vraiment remarquable à propos de JASS était qu'il avait un comptage de référence sur les poignées, mais ne les nettoyait pas à moins qu'elles ne soient détruites manuellement (et l'interface graphique créait des fonctions qui fuyaient de la mémoire partout)!
Craig Gidney

13

Le plus grand défaut de conception auquel je fais face est que python n'a pas été conçu comme python 3.x pour commencer.


1
Eh bien, même Guido ne peut pas tout faire d' un coup ...

5
@delnan, oh je sais, et python <3 est toujours un langage incroyablement bon, mais c'est un peu ennuyeux d'avoir un meilleur langage sous la forme de python 3.x que je ne peux pas utiliser car il casse tous les modules qui J'ai besoin de.
dan_waterworth

Continuez à faire pression pour vos modules python 3.x! En attendant, je continuerai d'écrire en 2.5.4. Grâce à SO, je me rappelle en fait que 3.x est bel et bien vivant.
kevpie

@kevpie Tout d'abord, faites pression pour ajouter une compilation conditionnelle à python afin de faciliter la transition pour les responsables de bibliothèque. 2to3 n'est pas une solution maintenable à long terme.
Evan Plaice

12

Décomposition de tableau en C et par conséquent C ++.


Je souhaite également un support de baie approprié. En C ++, vous pouvez empêcher la désintégration en utilisant la syntaxe et les modèles d'abscons ... mais c'est plus un hack: /
Matthieu M.

1
Notez que c'est la raison pour laquelle C ++ doit avoir des opérateurs deleteet séparés delete[].
dan04

Vous pouvez toujours mettre un tableau dans une structure et le faire passer par valeur si vous le souhaitez, mais cela est généralement plus gênant que le problème d'origine. En C ++, vous pouvez généralement éviter d'avoir à utiliser des tableaux.
David Thornley

2
Au moins dans le cas C, l'argument contre le support de tableau approprié est "la vérification des limites du tableau est coûteuse", en particulier compte tenu de la façon dont fonctionne l'arithmétique du pointeur C.
Stephen C

@Stephen C: Quelle vérification des limites du tableau a à voir avec la désintégration du tableau?
Nemanja Trifunovic

11

Types primitifs en Java.

Ils cassent le principe selon lequel tout est un descendant java.lang.Object, ce qui d'un point de vue théorique conduit à une complexité supplémentaire de la spécification du langage, et d'un point de vue pratique, ils rendent l'utilisation des collections extrêmement fastidieuse.

Autoboxing a aidé à atténuer les inconvénients pratiques mais au prix de rendre la spécification encore plus compliquée et d'introduire une grosse peau de banane grasse: vous pouvez maintenant obtenir une exception de pointeur nul à partir de ce qui ressemble à une simple opération arithmétique.


Cela entraînerait de graves problèmes de performances si vous supprimiez les types de primitives. Et l'autoboxing peut être gâché assez facilement, donc cela n'améliore rien.
deadalnix

À l'époque, c'était une décision sensée des concepteurs Java. Les gains de performances par rapport aux machines / VM disponibles dans les années 90 l'emportaient sur les avantages conceptuels d'unifier tout autour de java.lang.Object.
mikera

10

Je connais mieux Perl, alors je vais m'en occuper.

Perl a essayé de nombreuses idées. Certains étaient bons. Certains étaient mauvais. Certains étaient originaux et pas largement copiés pour une bonne raison.

L'une est l'idée de contexte - chaque appel de fonction a lieu dans un contexte de liste ou scalaire, et peut faire des choses entièrement différentes dans chaque contexte. Comme je l'ai souligné sur http://use.perl.org/~btilly/journal/36756, cela complique chaque API et conduit souvent à des problèmes de conception subtils dans le code Perl.

Le suivant est l'idée de lier si complètement la syntaxe et les types de données. Cela a conduit à l'invention du lien pour permettre aux objets de se faire passer pour d'autres types de données. (Vous pouvez également obtenir le même effet en utilisant la surcharge, mais l'attachement est l'approche la plus courante en Perl.)

Une autre erreur courante, commise par de nombreuses langues, est de commencer par proposer un cadrage dynamique plutôt que lexical. Il est difficile de revenir plus tard sur cette décision de conception et conduit à des verrues de longue durée. La description classique de ces verrues en Perl est http://perl.plover.com/FAQs/Namespaces.html . Notez que cela a été écrit avant que Perl ait ajouté des ourvariables et des staticvariables.

Les gens sont légitimement en désaccord sur le typage statique contre le typage dynamique. Personnellement, j'aime la frappe dynamique. Cependant, il est important d'avoir une structure suffisante pour permettre la capture des fautes de frappe. Perl 5 fait un bon travail avec strict. Mais Perl 1-4 s'est trompé. Plusieurs autres langues ont des vérificateurs de peluches qui font la même chose que strict. Tant que vous êtes bon dans l'application de la vérification des peluches, cela est acceptable.

Si vous cherchez plus de mauvaises idées (beaucoup d'entre elles), apprenez PHP et étudiez son histoire. Mon erreur passée préférée (corrigée il y a longtemps car elle entraînait tant de failles de sécurité) consistait à autoriser quiconque à définir n'importe quelle variable en passant des paramètres de formulaire. Mais c'est loin d'être la seule erreur.


5
Oui, Perl a beaucoup d'erreurs, parce que les gens qui l'ont construit essayaient de nouvelles idées, et quand vous le faites, vous vous trompez souvent. (Perl a également de très bonnes choses, et est la norme pour Regexps que tout le monde semble avoir copiée)
Zachary K

@ zachary-k: Tout à fait d'accord. Et j'ai essayé de le préciser avant de commencer à résoudre les problèmes.
btilly

4
Les lisps étaient à l'origine dynamiquement étendus, et au fil du temps, ils ont été modifiés pour être lexicalement étendus (au moins dans Scheme et Common Lisp). Ce n'est pas impossible de changer.
David Thornley

4
@ david-thornley: C'est impossible à moins que vous ne sacrifiez la compatibilité descendante quelque part. Le schéma était toujours de portée lexicale. Common Lisp a été délimité lexicalement depuis son standardisation, mais diverses communautés Lisp ont eu du mal à l'adopter. Et Emacs Lisp utilise toujours la portée dynamique, même s'il y a eu un désir de le changer depuis longtemps.
btilly

1
BTW, beaucoup de choses pour lesquelles les gens n'aiment pas Perl n'ont pas été inventées en Perl mais empruntées à d'autres langues, principalement le shell Bourne.
reinierpost

10

Ambiguïté JavaScripts pour les blocs de code et les littéraux d'objet.

  {a:b}

pourrait être un bloc de code, où aest une étiquette et best une expression; ou il pourrait définir un objet, avec un attribut aqui a la valeurb


J'aime vraiment cela à propos de JavaScript. La simplicité de la structure du langage est agréable et le but devrait être évident si le développeur sait ce qu'il fait.
Xeoncross

2
Xeoncross: Je n'aime généralement pas les ambiguïtés. Dans ce cas, c'est évident pour le développeur, mais eval () a besoin de parenthèses supplémentaires.
user281377

2
@ammoQ: C'est évident? Qu'est-ce que c'est alors? Un objet ou un bloc de code?
configurateur

configurateur: Evidemment un objet. Aucune personne sensée n'utiliserait une étiquette appelée a.
user281377

10

Je vais revenir sur FORTRAN et l'insensibilité des espaces.

Il imprègne la spécification. La ENDcarte devait être définie comme une carte avec un «E», un «N» et un «D» dans cet ordre dans les colonnes 7 à 72, et aucun autre non-blanc, plutôt qu'une carte avec «FIN» dans le bon colonnes et rien d'autre.

Cela a conduit à une confusion syntaxique facile. DO 100 I = 1, 10était une instruction de contrôle de boucle, tandis DO 100 I = 1. 10qu'une instruction affectait la valeur 1.1 à une variable appelée DO10I. (Le fait que des variables puissent être créées sans déclaration, leur type dépendant de leur première lettre, y a contribué.) Contrairement à d'autres langages, il n'y avait aucun moyen d'utiliser des espaces pour séparer les jetons pour permettre la désambiguïsation.

Cela a également permis à d'autres personnes d'écrire du code vraiment déroutant. Il y a des raisons pour lesquelles cette fonctionnalité de FORTRAN n'a plus jamais été dupliquée.


1
Dans une langue où vous pouvez redéfinir les littéraux, c'est le pire exemple - je veux dire que cela n'a provoqué le crash que d'un tout petit vaisseau spatial
Martin Beckett

Au début, vous pourriez écrire DAMNATION à la place de DIMENSION, et cela fonctionnerait.
Mike Dunlavey

Il est toujours enseigné par des personnes extérieures à CS. Je dois encore faire face à ceux qui a) se battent contre les déclarations, b) se battent contre les espaces blancs, c) comme les "lignes de continuation", d) utilisent des noms à 6 caractères, ou 4, d) sont perplexes quand ils voient (test ? a : b), e) insistent lors de l'utilisation **, f) ne peut pas gérer la casse. La plupart de cela était dû à des raccourcis clavier dans les années 50.
Mike Dunlavey

1
@Martin Beckett - la redéfinition des littéraux dans FORTRAN était vraiment une faille du compilateur plutôt qu'une fonctionnalité de langue. Ce n'était certainement pas une fonctionnalité de langage intentionnelle.
Stephen C

1
@oosterwal: Certainement. Je me trompe peut-être, mais je me souviens vaguement de la définition du langage basée sur les cartes perforées. Ils étaient le principal moyen d'entrer des programmes FORTRAN à l'époque, et l'idée d'une ligne de 80 colonnes avec des colonnes 73 à 80 réservées provient des cartes perforées.
David Thornley

9

L'un des plus gros problèmes avec BASIC était l'absence de méthode bien définie pour étendre le langage au-delà de ses premiers environnements, conduisant à un tas d'implémentations complètement incompatibles (et à une tentative post-facto presque non pertinente de normalisation).

Presque toutes les langues seront utilisées par un programmeur fou. Il est préférable de planifier cet usage général au début au cas où cette idée folle prend son envol.


2
+1: Toute langue sans modules et bibliothèques appropriés est une erreur qui attend de se produire. COBOL en a également souffert, ce qui a conduit à des variantes particulières qui ne sont pas compatibles.
S.Lott

8

Je crois aux DSL (domaines spécifiques au domaine) et une chose que j'apprécie dans une langue est si cela me permet de définir un DSL par-dessus.

En Lisp, il existe des macros - la plupart des gens considèrent cela comme une bonne chose, tout comme moi.

En C et C ++, il y a des macros - les gens s'en plaignent, mais j'ai pu les utiliser pour définir des DSL.

En Java, ils ont été laissés de côté (et donc en C #), et leur absence a été déclarée comme une vertu. Bien sûr, cela vous permet d'avoir Intellisense, mais pour moi, ce n'est qu'une œuvre . Pour faire mon DSL, je dois développer à la main. C'est une douleur, et cela me fait ressembler à un mauvais programmeur, même si cela me permet d'en faire beaucoup plus avec des tonnes de code en moins.


4
Je conviens que toute langue sans macros décentes est un énorme défaut de conception non corrigible. Mais que voulez-vous dire par « ils ont été exclus »? Le préprocesseur C n'était pas une sorte de macro système décent. Java n'est dérivé d'aucun langage approprié avec des macros.
SK-logic

1
Vous pouvez écrire votre DSL dans un langage de traitement de macro externe (comme m4, par exemple, parmi une myriade d'autres).
JUSTE MON AVIS correct

4
@SK: Je ne dirai pas que le préprocesseur C est un système de macro décent par rapport à Lisp (par exemple). Mais, par rapport à rien , c'est extrêmement utile.
Mike Dunlavey

4
@reinierpost: Je pense à des choses que je pourrais faire en Lisp, comme introduire des structures de contrôle telles que l'exécution différentielle et le retour arrière. Cela pourrait être fait avec des macros Lisp. En C / C ++, je pouvais faire une exécution différentielle avec des macros C (et un peu de discipline de programmeur), mais pas revenir en arrière. Avec C # je ne peux faire ni l'un ni l'autre. Ce que j'obtiens en échange, ce sont des choses comme Intellisense. BFD.
Mike Dunlavey

1
@ David: La façon dont je l'ai fait était que j'avais une macro pour envelopper le code ordinaire, comme une liste d'instructions. Il enlèverait cdrla liste et en ferait une fermeture lambda (c'est-à-dire une continuation) et la passerait en argument à carla liste. Cela a été fait de manière récursive, bien sûr, et "ferait la bonne chose" pour les conditions, les boucles et les appels de fonction. Ensuite, la fonction "choix" s'est transformée en boucle normale. Pas joli, mais c'était robuste. Le problème, c'est qu'il est très facile de créer des boucles trop imbriquées.
Mike Dunlavey

7

Déclarations , dans toutes les langues qui en ont. Ils ne font rien que vous ne pouvez pas faire avec les expressions et vous empêchent de faire beaucoup de choses. L'existence d'un ?:opérateur ternaire n'est qu'un exemple de la nécessité de les contourner. En JavaScript, ils sont particulièrement ennuyeux:

// With statements:
node.listen(function(arg) {
  var result;
  if (arg) {
    result = 'yes';
  } else {
    result = 'no';
  }
  return result;
})

// Without:
node.listen(function(arg) if (arg) 'yes' else 'no')

Je suis confus ici: voulez-vous simplement une façon plus simple de faire les choses?
TheLQ

2
Correct. Des expressions pour tout.
munificent

1
Lisp fonctionne bien pour cela.
David Thornley

1
@ SK-logic: Je soupçonne que les déclarations ont été aveuglément héritées du langage machine, via FORTRAN, ALGOL et COBOL.
David Thornley

1
Je suis à peu près sûr que le langage machine est l'ancêtre commun, et cela ne fait que refléter le fait que les ordinateurs modernes basés sur l'architecture von Neumann exécutent les instructions séquentiellement et modifient l'état. En fin de compte, lorsque IO se produira, il y aura des expressions qui ne produiront pas de données significatives, donc les instructions ne sont pas entièrement inutiles pour indiquer sémantiquement qu'un code n'a que des effets secondaires. Même les langages qui ont une notion de unittype (aka ()) au lieu d'instructions ont une attention particulière pour s'assurer qu'ils ne lancent pas d'avertissement ou ne se comportent pas de manière étrange.
Rei Miyasaka

6

Pour moi, c'est le problème de conception qui afflige tous les langages dérivés du C; à savoir, le « balançant d'autre ». Ce problème grammatical aurait dû être résolu en C ++, mais il a été appliqué à Java et C #.


3
L'un des principaux objectifs du C ++ était d'être entièrement rétrocompatible avec C. S'ils avaient radicalement changé le comportement sémantique, il n'aurait peut-être pas pris le relais comme il l'a fait (ou du moins, c'était l'idée à l'époque)
Ed S.

2
@Ed S., cependant, l'élimination du problème de "balançoire d'autre" aurait pu être accomplie en éliminant la <compound_statement> (aka <block>) production grammaticale et en incorporant les accolades dans les structures de contrôle conditionnelles et itératives comme ils le faisaient quand ils a ajouté la structure de contrôle de gestion des exceptions try / catch. Il n'y a aucune excuse pour ne pas rectifier cette ambiguïté grammaticale en Java et C #. Actuellement, le travail défensif autour de cette ambiguïté grammaticale consiste à faire de chaque instruction qui suit une instruction de contrôle conditionnelle ou itérative une instruction composée.
bit-twiddler

1
Que veux-tu dire par là? Ce n'est pas un «problème grammatical» (c'est complètement sans ambiguïté). Comment le «résoudriez-vous»? En fait, je trouve les règles en C satisfaisantes. Sans doute, seule une syntaxe de type Python (= indentation significative) peut vraiment résoudre ce problème. De plus, je suis en fait très heureux que les langues modernes n'imposent pas d' accolades. Je suis d'accord pour dire que toutes les syntaxes de type C sont nulles mais ballantes, sinon le moindre de leurs problèmes.
Konrad Rudolph

1
Poursuivant: je pense que l'utilisation par Python d'une indentation comme moyen de délimiter une liste de déclarations est bizarre au-delà de toute croyance. Cette technique viole le principe de «séparation des préoccupations» en couplant étroitement le balayage lexical avec l'analyse syntaxique. Une grammaire sans contexte devrait pouvoir être analysée sans rien savoir de la disposition de la source.
bit-twiddler

3
@ bit-twiddler: Non, ce n'est pas le cas. Le lexer Python convertit simplement l'espace blanc en jetons INDENT et DEDENT appropriés. Une fois cela fait, Python a une grammaire assez conventionnelle ( docs.python.org/reference/grammar.html ).
dan04

6

Je pense que toutes les réponses jusqu'à présent pointent vers un seul échec de nombreuses langues dominantes:

Il n'y a aucun moyen de changer le langage principal sans affecter la compatibilité descendante.

Si cela est résolu, à peu près tous ces autres reproches peuvent être résolus.

MODIFIER.

cela peut être résolu dans les bibliothèques en ayant différents espaces de noms, et vous pourriez concevoir de faire quelque chose de similaire pour la plupart du cœur d'un langage, bien que cela puisse signifier que vous devez prendre en charge plusieurs compilateurs / interprètes.

En fin de compte, je ne pense pas savoir comment le résoudre d'une manière totalement satisfaisante, mais cela ne signifie pas qu'il n'existe pas de solution, ou que plus ne peut être fait.


1
Comment feriez-vous pour "résoudre" cela?
Bjarke Freund-Hansen

Je ne suis pas sûr que cela puisse être totalement résolu - évidemment, garder les choses hors du langage principal et dans une bibliothèque standard aide donc je pense que j'essaierais de pousser cela aussi loin que possible
jk.

1
Par rétrocompatibilité, voulez-vous dire que les nouveaux compilateurs devraient être en mesure de compiler l'ancien code?
Rei Miyasaka

Je veux dire que les nouveaux compilateurs ne devraient pas changer la signification de l'ancien code, échouer à compiler serait un sous-ensemble de cela
jk.

dans la plupart des cas, lorsqu'une fonctionnalité particulière n'existe pas ou veut changer, les utilisateurs créent une nouvelle langue basée sur la précédente. C avec classes => C ++
umlcat


4

Java et C # ont tous deux des problèmes gênants avec leurs systèmes de type en raison du désir de maintenir la compatibilité descendante lors de l'ajout de génériques. Java n'aime pas mélanger les génériques et les tableaux; C # n'autorisera pas certaines signatures utiles car vous ne pouvez pas utiliser des types de valeur comme limites.

À titre d'exemple de ce dernier, considérons que

public statique T Parse <T> (Type <T> type, chaîne str) où T: Enum
à côté ou en remplacement
objet statique public Parse (type type, chaîne str)
dans la Enumclasse permettrait
MyEnum e = Enum.Parse (typeof (MyEnum), str);
plutôt que tautologique
MyEnum e = (MyEnum) Enum.Parse (typeof (MyEnum), str);

tl; dr: pensez au polymorphisme paramétrique lorsque vous commencez à concevoir votre système de type, pas après avoir publié la version 1.


2
L'incapacité de restreindre les types à l'énumération est ennuyeuse en C #, mais vous pouvez le contourner comme ceci MyMethod<T>(T value) where T : struct, IComparable, IFormattable, IConvertible Mais vous devez toujours tester une énumération et c'est un hack. Je pense que le plus grand manque dans les génériques C # n'est pas un support pour les types supérieurs, ce qui ouvrirait vraiment le langage à certains concepts sympas.
CodexArcanum

4

J'ai l'impression de m'ouvrir pour être flambé, mais je déteste vraiment la possibilité de passer de vieux types de données simples par référence en C ++. Je déteste seulement légèrement pouvoir passer des types complexes par référence. Si je regarde une fonction:

void foo()
{
    int a = 8;
    bar(a);
}

Du point d'appel, il n'y a aucun moyen de dire que bar, qui peut être défini dans un fichier complètement différent, est:

void bar(int& a)
{
    a++;
}

Certains pourraient faire valoir que faire quelque chose comme ça peut simplement être une mauvaise conception de logiciel, et ne pas blâmer la langue, mais je n'aime pas que la langue vous permette de le faire en premier lieu. Utiliser un pointeur et appeler

bar(&a);

est beaucoup plus lisible.


+1 Je ne suis pas d'accord avec vous, mais j'apprécie votre raisonnement.
Jon Purdy

@Jon Je serais en fait très intéressé par ce que vous en pensez. Portez-vous la vue «ne blâmez pas la langue»?
Jeff

6
@Jeff: D'une part, la raison principale pour laquelle la sémantique de référence a fait son chemin en C ++ était la surcharge des opérateurs, pour laquelle un comportement de référence uniforme est tout simplement logique. Plus important encore, cependant, C ++ est conçu pour être polyvalent et fournir des fonctionnalités très fines, même si cela entraîne un risque important d'erreur de programmation. Alors oui, au moins dans ce cas particulier, ne blâmez pas la langue. Je préfère être capable de faire des erreurs que de laisser une langue me gêner.
Jon Purdy

@Jon a accepté, il serait très étrange que le renvoi par référence s'applique à tout sauf aux POD. Je préférerais que cette fonctionnalité soit totalement absente du C ++ comme alternative, mais nous pouvons accepter d'être en désaccord :). Merci pour la contribution!
Jeff

Java ne semble pas aimer les pointeurs autant que vous.
Mateen Ulhaq

4

MODIFIER

Lorsque j'ai appris COBOL, l'instruction ALTER faisait toujours partie de la norme. En résumé, cette instruction vous permet de modifier les appels de procédure pendant l'exécution.

Le danger était que vous puissiez mettre cette déclaration dans une section obscure du code à laquelle on accédait rarement et qui avait le potentiel de changer complètement le flux du reste de votre programme. Avec plusieurs instructions ALTER, vous pourriez rendre presque impossible de savoir ce que faisait votre programme à un moment donné.

Mon professeur d'université, très catégoriquement, a déclaré que s'il voyait cette déclaration dans l'un de nos programmes, il nous ferait automatiquement échouer.


Il a cependant de bons cas d'utilisation - stubbing ou memoization. Au lieu d'écrire v() { if (not alreadyCalculatedResult) { result = long(operation); alreadyCalculatedResult = true; } result; }vous ditesv() { result = long(operation); v = () => result; result; }
configurateur

4

Le pire péché d'un langage de programmation n'est pas bien défini. Un cas dont je me souviens est le C ++, qui, dans ses origines:

  1. Était si mal défini que vous ne pouviez pas obtenir un programme à compiler et à exécuter en suivant des livres ou des exemples.
  2. Une fois que vous avez modifié le programme pour compiler et exécuter sous un compilateur et un système d'exploitation, vous devrez recommencer si vous avez changé de compilateur ou de plate-forme.

Si je me souviens bien, il a fallu environ une décennie pour que le C ++ soit suffisamment bien défini pour le rendre aussi fiable sur le plan professionnel que C. C'est quelque chose qui ne devrait plus jamais se reproduire.

Quelque chose d'autre que je considère comme un péché (devrait-il aller dans une réponse différente?) Est d'avoir plus d'une "meilleure" façon de faire une tâche commune. C'est le cas (encore) de C ++, Perl et Ruby.


1
Je ne vois pas comment éviter le flou dans une langue en évolution. Ou, d'ailleurs, dans un langage prédéfini où le concepteur d'origine a raté certains points importants (comme Pascal).
David Thornley

@David Thornley Une définition bien définie est bien définie. Résistant aux bugs, la plupart des concepteurs de langages de programmation le comprennent dès le départ. Les outils peuvent vérifier qu'une grammaire n'est pas ambiguë lorsqu'elle est terminée (C ++ nécessite au moins trois grammaires), et la sémantique doit être spécifiée pour les implémentations standard.
Apalala

Je suis d'accord que des langages bien définis sont possibles, mais cela ne se produira pas dans un langage évolutif comme le C ++ pré-standard. L'alternative est que chaque langue est soigneusement conçue avant sa sortie, et ce n'est pas nécessairement le moyen d'obtenir les meilleures langues. Je dirais que la plupart des concepteurs de langage de programmation se trompent au début, car la conception du langage est extrêmement compliquée.
David Thornley

Je suppose que j'ai du mal à comprendre ce que vous entendez par «bien défini». Votre plainte est-elle que différents compilateurs C ++ n'ont pas réellement compilé le même langage?
Sean McMillan

3

Les classes en C ++ sont une sorte de modèle de conception forcée dans le langage.

Il n'y a pratiquement pas de différence au moment de l'exécution entre une structure et une classe, et il est tellement déroutant de comprendre quel est le véritable avantage de programmation de la "dissimulation d'informations" que je souhaite la mettre là.

Je vais être rétrogradé pour cela, mais de toute façon, les compilateurs C ++ sont si difficiles à écrire que ce langage ressemble à un monstre.


2
Le masquage des informations est important car il vous permet de masquer les détails spécifiques à l'implémentation, qui sont susceptibles de changer, des parties accessibles de l'API (l '"interface utilisateur" de l'API), ce qui rend les modifications du programme plus faciles et moins douloureuses.
Anto

1
L'interface utilisateur de l'API ... non, sérieusement, je ne l'achète pas.
jokoon

3
Cette différence n'est pas la partie la plus révoltante de C ++, même pas proche. La seule différence est un modificateur d'accès par défaut (public pour les structures, privé pour les classes). Le C ++ est un langage horrible et monstrueux, mais certainement pas dans cette partie.
SK-logic

sk-logic: eh bien, je pourrais dire que les horreurs commencent là.
jokoon

2
La dissimulation d'informations est bonne; vous pouvez trouver des discussions à ce sujet partout. Le seul livre de logiciel de premier plan auquel je puisse penser qui était contre était le "Mois mythique de l'homme" de Brooks, et il l'a considéré plus tard comme la plus grosse erreur du livre. Si vous ne comprenez pas les avantages, vous n'êtes vraiment pas qualifié pour porter le jugement que vous portez.
David Thornley

3

Bien que chaque langue ait ses défauts, aucune n'est une nuisance une fois que vous les connaissez. Sauf pour cette paire:

Syntaxe complexe couplée à une API verbeuse

Cela est particulièrement vrai pour un langage comme Objective-C. Non seulement la syntaxe est extrêmement complexe, mais l'API utilise des noms de fonction comme:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

Je suis tout à fait explicite et sans ambiguïté, mais c'est ridicule. Chaque fois que je m'assois avec xcode, je me sens comme un n00b, et c'est vraiment frustrant.


La syntaxe Objective-C est extrêmement complexe? Vous n'avez pas vu C ++? Et le nom réel de la méthode tableView:cellForRowAtIndexPath:, qui est très descriptif à mon avis.
plié à droite

Apprenez à taper.
finnw

2
  1. caractères signés en C - une abomination inventée pour permettre aux mathématiciens d'avoir de grandes collections de petits objets
  2. Utiliser le cas pour transporter du contenu sémantique - encore une fois pour les mathématiciens, qui n'ont pas besoin de parler et qui n'ont jamais assez d'espace pour leurs formules
  3. Affectation Let / Plain vs. Set Assignation dans les dialectes de base - pas de mathématiciens impliqués ici je pense

Je suis perdu quant à votre commentaire de caractère signé, pourriez-vous expliquer?
Winston Ewert

1
Pour un humain, le concept de caractères (non) signés et la nécessité de dire au compilateur d'utiliser des caractères non signés par défaut est sûrement aussi fou que pour un mathématicien l'affirmation que 2! = 2, parce que le second 2 est en majuscules, en gras ou en italique.
Ekkehard.Horner

5
Le problème est que C confond le concept de "char" (c'est-à-dire une partie d'une chaîne de texte) et "byte" (c'est-à-dire (u)int_least8_t). La signature est parfaitement logique pour les petits entiers, mais n'a aucun sens pour les caractères.
dan04

@ dan04: Je suis d'accord, je souhaite qu'ils aient différents types pour les petits entiers (signés et non signés), octets et caractères. Lorsque vous expliquez aux débutants que pour manipuler la mémoire brute, ils doivent transtyper en char*... comme une chaîne C, ils deviennent vraiment confus.
Matthieu M.

C # a ce droit avec séparés sbyte, byteet chartypes.
dan04
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.