Quel élément de syntaxe détestez-vous le plus dans un langage de programmation que vous utilisez fréquemment? [fermé]


27

Peu importe combien vous aimez un langage de programmation, il y a toujours quelques détails qui ne sont pas aussi agréables qu'ils pourraient l'être.

Dans cette question, je voudrais me concentrer spécifiquement sur les éléments de syntaxe. Dans un langage de programmation que vous utilisez fréquemment (peut-être votre langage de programmation préféré, ou peut-être celui que vous êtes obligé d'utiliser au travail), quel élément de syntaxe trouvez-vous le plus illisible, peu clair, incommode ou désagréable?


@Nathan Taylor, pas pour cette question, mais pour une autre question .
finnw

Cette question a-t-elle été modifiée? Parce que quand j'ai répondu, ce n'était pas concentré sur les "éléments de syntaxe" ... Je vais devoir modifier ma réponse maintenant.
Talvi Watia

@Talvi: Non, il s'agissait de la syntaxe dès le début.
Timwi

@Timwi bizarre, il doit s'agir de «répondre à une question en pensant qu'elle était différente».
Talvi Watia

Si vous pouvez voter et pensez que c'est une question utile ou si vous avez des réponses utiles ci-dessous, veuillez voter. Les sites StackExchange ont besoin de votes pour construire une bonne communauté. Vous pouvez donner 30 votes par jour, ne les gaspillez pas. Particulièrement les utilisateurs ayant une grande réputation et un faible nombre de votes comptés donnés, veuillez lire ceci: meta.programmers.stackexchange.com/questions/393/…
Maniero

Réponses:


39

Insertion de points-virgules en JavaScript.

Je n'ai pas vraiment été mordu souvent, mais c'est juste une si mauvaise idée que ça me fait tourner la tête.


Voici les règles (de la section 7.9 de l'ECMA-262)

  1. Lorsque le programme contient un jeton qui n'est pas autorisé par la grammaire formelle, un point-virgule est inséré si (a) il y a un saut de ligne à ce point, ou (b) le jeton inattendu était une accolade fermante.
  2. Lorsque la fin d'un fichier est atteinte, si le programme ne peut pas être analysé autrement, un point-virgule est inséré.
  3. Lorsqu'une "production restreinte" est rencontrée et contient un terminateur de ligne à un endroit où la grammaire contient l'annotation "[pas de LineTerminator ici]", un point-virgule est inséré.

Exemple:

return 1; // returns 1

return
1; // returns undefined

2
JavaScript: le langage de programmation le plus mal compris au monde ~ Douglas Crockford
pramodc84

Oui, beaucoup s'attendent à ce que JavaScript soit un "langage de forme libre", mais ce n'est pas le cas.
Andreas Rejbrand

13
Cela a du sens une fois que vous vous rendez compte que JavaScript a été conçu pour créer du HTML, qui a également une longue histoire d'essayer d'interpréter ce que votre code "signifie vraiment" lorsqu'il n'est pas syntaxiquement valide. (Recherchez le principe de robustesse parfois - le plus grand désastre de l'histoire de l'informatique.)
Mason Wheeler

7
Ces types d'erreurs, pour moi, sont une odeur de code que le programmeur est bâclé et n'a jamais travaillé avec la plupart des langages "stricts" formels qui provoqueraient normalement une erreur de syntaxe pour laisser le point-virgule hors.
Talvi Watia

7
Wohoo, enfin quelqu'un d'autre qui pense aussi que le principe de robustesse est une catastrophe qui a fait de HTML le désordre absolu qu'il est.
Roman Starkov

39

Syntaxe Java-bean en raison du manque de propriétés C #

/**
 * Name of user
 */
private String name;

/**
 * Gets name of user
 * @return Name of user
 */
public String getName() {
    return this.name;
}

/**
 * Sets name of user. 
 * @param name
 */
public void setName(final String name) {
    this.name = name;
}

GAH !!!

Problèmes que j'ai avec cela

  • Trop de code - Ayez un champ documenté, une méthode getter documentée et une méthode setter documentée. Cet exemple extrêmement basique a 20 lignes de code pour une seule propriété
  • Clutter listes de méthode - « Permettez - moi de trouver cette méthode, la main sur: getX, getY, getZ, getAnotherAnnoyingField, getWhyIHateJavaBeans, getThisIsVerbose, getGAH... ah ça y est, hashCode.
  • Plusieurs domaines de documentation entraînent une documentation médiocre, obsolète ou manquante - ennuyeux lorsque vous essayez de comprendre ce que fait le code
  • Donc, un tiers ennuyeux devait trouver un plugin pour le faire facilement - Spoon , Shark , entre autres.

9
Encore une fois, lorsque le code est tellement verbeux qu'il a besoin d'outils de génération automatique, quelque chose ne va pas. Je suis un gars de NetBeans, mais il a également la capacité de générer automatiquement des getters et des setters. Mais Javadoc tombe en désaccord, il est toujours verbeux, il encombre toujours javadoc, etc.
TheLQ

11
Si vous avez besoin de getters pour tout, alors quelque chose ne va pas avec le code client .
finnw

7
Le fait d'avoir des getters et des setters rompt l'encapsulation. Le domaine pourrait tout aussi bien l' être public. Les membres doivent être privés et doivent être manipulés de manière sensible par la classe avec une logique de niveau supérieur, pas avec des getters et des setters à partir du code client.
greyfade

6
@greyfade: S'il est public, vous ne pouvez pas facilement changer ce que fait le code de réglage (vous devrez changer tout le code qui définit le champ de l'extérieur).
Bart van Heukelom

3
@SHiNKiROU: Java a l'air propre? Je n'en ai jamais entendu parler auparavant! Mon principal reproche avec Java est le fait qu'une chose apparemment simple nécessite des dizaines de lignes de code que je dois ignorer mentalement.
configurateur

33

Sensibilité des espaces.

Python m'énerve à cet égard. Je veux dire, je fais un retrait correct de toute façon, mais ça me dérange que je doive le faire . Faire de la présentation une partie de la syntaxe m'énerve.


8
vous apprendrez à l'aimer
user10008

2
la syntaxe est la présentation
Winston Ewert

32

L' switchinstruction (en C, C ++, C #, Java, etc.)

Voici un exemple des raisons pour lesquelles je trouve cela très gênant:

switch (someVariable)
{
    case 1:
        int i = something();
        doSomething(i);
        break;

    case 2:
        int i = somethingElse();
        doSomethingElse(i);
        break;
}

Cela ne se compile pas car la variable iest redéclarée dans la même étendue. Cela semble être un détail mineur, mais il me mord très souvent. Je peux ajouter des accolades pour l'atténuer, mais cela aurait été bien si les accolades avaient été une partie obligatoire de la syntaxe, et il n'y avait pas de niveau supplémentaire d'indentation redondant. Je déteste aussi vraiment avoir à écrire le supplément break. Ce serait bien mieux:

switch (someVariable)
case 1
{
    int i = something();
    doSomething(i);
}
case 2
{
    int i = somethingElse();
    doSomethingElse(i);
}
default
{
    ...
}

Cela le fait ressembler davantage à une chaîne if/ else, ce qui est une bonne chose car il est également sémantiquement similaire. Au moins en C #, ce ne serait pas la même chose cependant, car dans une switchdéclaration, l'ordre des étiquettes de cas n'a pas d'importance, mais dans un if/ elseil le fait.


1
Malheureusement, votre syntaxe améliorée supprime ce qui est, sans doute, la plus grande fonctionnalité du commutateur dans la plupart de ces langages: Fall-through. "Le dispositif de Duff" en C est un parfait exemple de la valeur de cette "caractéristique erronée" particulière. Il est également courant dans les langages de type C d'utiliser la fonction d'interruption dans les interprètes et les programmes similaires.
greyfade

7
Non, cela ne l’élimine pas. Il suffit de le rendre plus explicite (en utilisant un gotoou similaire), comme c'est déjà le cas en C #.
Timwi

8
@greyfade: Tout code utilisant l'appareil de duff en C doit mourir d'une mort horrible. Les compilateurs prennent de meilleures décisions sur ce genre de choses que vous.
Billy ONeal

4
@greyfade: Delphi obtient autour de la question de la valeur multiple en permettant simplement plusieurs indices dans le cas: case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;.
Frank Shearar

3
@jkerian: Imaginez maintenant que breakc'était la valeur par défaut et que seule la solution devait être spécifiée. Plus besoin de vous souvenir de le commenter! :)
Timwi

27

Déclarations de tableau dans VB.NET

J'arrive toujours à oublier que lors de l'initialisation de tableaux fixes dans VB.NET, vous spécifiez la limite supérieure du tableau et non le nombre d'éléments comme en C / C ++, PHP ou Java. Outre VB6 (nous n'irons pas là-bas ...), je ne peux pas penser à une autre langue qui le fasse de cette façon:

Dim myArray(20) as Integer  '# Creates an array with 21 elements,
                            '# indexed from 0 to 20

Je pense que tous les langages BASIC le font ... Je sais que le BASIC et le QBasic originaux le font.
Michael K

OMG qui est vraiment horrible .... +1
mikera

25

VB6 - Déclaration et affectation de variable distincte

La plupart des langues vous permettent de déclarer une variable et de l'assigner sur une seule ligne de code; VB6, d'autre part, vous oblige à en utiliser deux.

Dim i as Integer
i = 0

Dim derpderp as Collection
Set derpderp = new Collection

Vous pouvez utiliser deux points pour mettre deux commandes sur une seule ligne, mais cela devient rapidement désordonné dans le code réel.

Dim i as Integer: i = 0
Dim derpderp as Collection: Set derpderp = new Collection

7
+1 pour avoir à utiliser VB6 comme langue la plus fréquente.
Walter

9
Je l'utilise tous les jours.
systempuntoout

Pascal n'a-t-il pas une syntaxe similaire? J'ai toujours pensé que c'était méchant.
greyfade

1
Il y a un cas particulier: si vous Dim Hurp As New Collection, si vous accédez Hurpquand il se réfère Nothing, il sera magiquement initialisé avant l'accès. Si vous le définissez explicitement Nothinget le touchez à nouveau, il est ressuscité ... halètement!
Jeffrey Hantin

1
+ 1 million pour Derp. Derp de derp de tiddly tum de derp.
MVCylon

24

Commenter en CSS

//ne commente pas les lignes de code comme il le fait dans de nombreux autres langages, comme PHP et Javascript. Bien que /* this is commented out */fonctionne, je préfère utiliser //.

C'est une nuisance, car la moitié du temps, j'oublie que je modifie le CSS et que je dois ensuite revenir en arrière et corriger l'erreur.


Vous penseriez de nos jours que le CSS brut serait considéré comme du code objet.
Tom Hawtin - tackline

// fonctionne très bien pour commenter CSS. Je le fais tout le temps. Je ne fais que taper des ordures. mais cela semble fonctionner en sautant la ligne insaisissable.
MVCylon

1
@MVCylon Si vous utilisez // pour commenter une ligne, tout ce qui se trouve après la ligne suivante est également ignoré. {dans ce style spécifique} En d'autres termes, il ÉCHoue car ces lignes ne doivent pas être ignorées.
Talvi Watia

20

PHP - ordre cohérent des arguments

PHP a un certain nombre de fonctions pratiques pour faire à peu près toutes les opérations auxquelles vous pouvez penser sur un tableau ou une chaîne. Beaucoup de ces opérations nécessitent d'utiliser à la fois a $needleet a $haystack, mais différentes fonctions les prennent dans des ordres différents. Quelle fonction nécessite quels arguments est l'un de ces faits que mon cerveau refuse d'absorber, peu importe la fréquence à laquelle je les rencontre!

Prenez les fonctions in_array et strstr :

// Check whether $needle occurs in array $haystack
bool in_array (mixed $needle, array $haystack [, bool $strict])

// Check whether $needle is a substring of $haystack
string strstr (string $haystack, mixed $needle [, bool $before_needle=false])

Curieusement, PHP semble être cohérent en interne avec ces ordres dans la mesure où toutes les fonctions de chaîne semblent utiliser $haystack, $needletandis que les fonctions de tableau sont l'inverse, mais cela peut prendre un peu de temps pour s'habituer à quelqu'un de nouveau en PHP. Il y a un bon article sur ExpressionEngine qui parle plus en détail de cette bizarrerie particulière, ainsi qu'une discussion sur la liste des bogues PHP , qui présente une réponse très courte de l'équipe PHP!

helly@php.net
Utilisez alors un IDE décent.

2
Il est plus facile de se souvenir de l'ordre $needle, $haystackcar il rappelle la façon de dire trouver une aiguille dans une botte de foin .
kiamlaluno

3
Protip: dans les fonctions de tableau, l'aiguille vient en premier. dans les fonctions de chaîne, la botte de foin vient en premier.
GSto

17
J'adore le nom strstr. Si magnifiquement dénué de sens.
configurateur

5
Il suffit de lire l'entrée liée dans le bugtracker de PHP. Sérieusement, wtf? o La cohérence Imho est un problème valide pour n'importe quelle API et répondre simplement par "utiliser un IDE décent alors" n'est tout simplement pas une réponse valide. Au moins, il aurait pu être rédigé comme moins incendiaire par les développeurs.
Baelnorn

2
Honnêtement, ce qui me rend fou, c'est que cela ne devrait pas du tout être une fonction! Ce devrait être juste une méthode: $ haystack-> find ($ needle). Terminé.
riwalk

19

Python

self paramètre dans les définitions de méthode d'instance


Dans une méthode de classe, elle est généralement nommée cls et l'utilisation de self va à l'encontre de la convention.

Cela a du sens si vous y réfléchissez. C'est la même chose que déclarer une méthode privée dans d'autres langages, le paramètre self est juste explicite en python où il est implicite dans d'autres langages. Si vous voulez qu'il soit implicite, ajoutez le décorateur @classmethod avant la déclaration de méthode. Voir docs.python.org/library/functions.html#classmethod . Apprendre les détails de la façon dont cela fonctionne vous donnera un aperçu de la manière implicite dans d'autres langues.
Evan Plaice

4
Je comprends les raisons et pourquoi il est laissé là neopythonic.blogspot.com/2008/10/… mais je ne l'aime toujours pas
Goran Peroš

@Evan Plaice: 'l'auto-paramètre est juste explicite en python où il est implicite dans d'autres langues' Ce n'est qu'une partie de l'histoire. L'autre partie est le python tapé chaque semaine. Ensemble, c'est terrible, l'oubli selfarrive facilement et coûte du temps.
maaartinus

@maaartinus Ajoutez ensuite un décorateur de méthode de classe à vos méthodes d'instance. N'a rien à voir avec «faiblement typé». Il rend juste évidente la relation entre les méthodes / fonctions statiques (pas de paramètre «self») et les méthodes d'instance (inclut «self»). Une méthode d'instance n'est pas consciente de sa classe parent, sauf si vous lui donnez une référence pour le faire. Dans d'autres langues, la caractéristique distinctive que j'ai décrite est juste cachée derrière le sucre syntaxique. Si j'avais eu le choix de tout faire, j'aurais commencé par apprendre OOP en Python en premier.
Evan Plaice

18

Java

Période. Arrêt complet. Fin de l'histoire.

Où commencer? Oh, je sais par où commencer: les génériques de Java incroyablement compliqués et laids et stupides et intrinsèquement cassés . Dois-je en dire plus? :( Ok bien, alors: tapez l'effacement .

Ensuite, il y a la gestion non déterministe des ressources. Kewl feetcher!

Quelle est la prochaine étape? Oh ouais: les stupides regex de Java sont mon boeuf le plus irritant et bouillonnant. Je ne peux pas compter le nombre de fois où j'ai été arrosé parce que je n'ai pas suffisamment de barres obliques inverses. C'est encore pire que de ne pas avoir accès aux propriétés Unicode de ce millénaire - ce qui est un taureau complet. Dix ans effrayants dépassés !!! Totalement inutile. Trash it.

Ensuite, il y a le bogue que les raccourcis de classe de caractères ne fonctionnent pas sur non-ASCII. Quelle douleur royale! Et n'envisagez même pas d'utiliser \p{javaWhiteSpace}; il ne fait pas la bonne chose avec plusieurs points de code d'espaces blancs Unicode très courants.

Saviez-vous qu'il y a une \p{javaJavaIdentifierStart}propriété? À quoi pensaient-ils? Je suis tellement content qu'ils aient eu de tels voyants intelligents wurkin sur dis difficile.

Avez-vous déjà essayé d'utiliser l'indicateur CANON_EQ? Savez-vous que c'est vraiment le cas et ce qu'il ne fait pas ? Qu'en est-il du soi-disant «boîtier Unicode»? Un tas de boîtiers normaux ne fonctionnent tout simplement pas.

Ensuite, il est difficile d'écrire des expressions rationnelles maintenables. Java n'a toujours pas compris comment écrire des chaînes multilignes, vous finissez donc par écrire des choses folles comme ceci:

    "(?= ^ [A-Z] [A-Za-z0-9\\-] + $)      \n"
  + "(?! ^ .*                             \n"
  + "    (?: ^     \\d+      $            \n"
  + "      | ^ [A-Z] - [A-Z] $            \n"
  + "      | Invitrogen                   \n"
  + "      | Clontech                     \n"
  + "      | L-L-X-X                      \n"
  + "      | Sarstedt                     \n"
  + "      | Roche                        \n"
  + "      | Beckman                      \n"
  + "      | Bayer                        \n"
  + "    )      # end alternatives        \n"
  + ")          # end negated lookahead   \n" 

Quelles sont toutes ces nouvelles lignes? Oh, juste la stupidité Java. Ils ont utilisé des commentaires Perl, pas des commentaires Java ( idiots! ) Qui vont jusqu'à la fin de la ligne. Donc, si vous ne les mettez pas \nlà, vous coupez le reste de votre modèle. Duh et double duh!

N'utilisez pas d'expressions régulières en Java: vous finirez par vouloir casser des choses, tout cela est si douloureux et cassé. Je ne peux pas croire que les gens supportent ça. Certains non .

Ensuite, nous pouvons commencer à parler du non-sens idiot de Java avec des encodages. Tout d'abord, il y a le fait que le codage par défaut de la plate-forme est toujours un codage 8 bits boiteux même si les charchars de Java sont Unicode. Ensuite, il y a comment ils ne déclenchent pas d'exception en cas d'erreur de codage. Vous êtes assuré d'obtenir de la merde. Ou que diriez-vous de ceci:

OutputStreamWriter(OutputStream out) 
          Creates an OutputStreamWriter that uses the default character encoding.
OutputStreamWriter(OutputStream out, Charset cs) 
          Creates an OutputStreamWriter that uses the given charset.
OutputStreamWriter(OutputStream out, CharsetEncoder enc) 
          Creates an OutputStreamWriter that uses the given charset encoder.
OutputStreamWriter(OutputStream out, String charsetName) 
          Creates an OutputStreamWriter that uses the named charset.

Quelle est la différence? Saviez-vous qu'un seul de ceux-ci lèvera une exception si vous avez une erreur d'encodage? Les autres les muselent.

Ensuite, il y a l'idiotie des caractères Java qui ne suffisent pas à contenir un personnage! Que diable pensent-ils? C'est pourquoi je les appelle des charchars. Vous devez écrire du code comme celui-ci si vous pensez qu'il fonctionne correctement:

private static void say_physical(String s) { 
    System.out.print("U+");
    for (int i = 0; i < s.length(); i++) {
        System.out.printf("%X", s.codePointAt(i));
        if (s.codePointAt(i) > Character.MAX_VALUE) { i++; }  // UG!
        if (i+1 < s.length()) { System.out.printf("."); }
    }
}

Et qui pense faire ça? À côté de personne.

Combien de personnages y a-t-il "\uD83D\uDCA9"? Un ou deux? Cela dépend de la façon dont vous les comptez. Le moteur d'expression régulière traite bien sûr des caractères logiques, donc un modèle ^.$réussira et un modèle ^..$échouera. Cette folie est démontrée ici:

String { U+61, "\u0061", "a" }  =~ /^.$/ => matched.
String { U+61, "\u0061", "a" }  =~ /^..$/ => failed.
String { U+61.61, "\u0061\u0061", "aa" }  =~ /^.$/ => failed.
String { U+61.61, "\u0061\u0061", "aa" }  =~ /^..$/ => matched.
String { U+DF, "\u00DF", "ß" }  =~ /^.$/ => matched.
String { U+DF, "\u00DF", "ß" }  =~ /^..$/ => failed.
String { U+DF.DF, "\u00DF\u00DF", "ßß" }  =~ /^.$/ => failed.
String { U+DF.DF, "\u00DF\u00DF", "ßß" }  =~ /^..$/ => matched.
String { U+3C3, "\u03C3", "σ" }  =~ /^.$/ => matched.
String { U+3C3, "\u03C3", "σ" }  =~ /^..$/ => failed.
String { U+3C3.3C3, "\u03C3\u03C3", "σσ" }  =~ /^.$/ => failed.
String { U+3C3.3C3, "\u03C3\u03C3", "σσ" }  =~ /^..$/ => matched.
String { U+1F4A9, "\uD83D\uDCA9", "💩" }  =~ /^.$/ => matched.
String { U+1F4A9, "\uD83D\uDCA9", "💩" }  =~ /^..$/ => failed.
String { U+1F4A9.1F4A9, "\uD83D\uDCA9\uD83D\uDCA9", "💩💩" }  =~ /^.$/ => failed.
String { U+1F4A9.1F4A9, "\uD83D\uDCA9\uD83D\uDCA9", "💩💩" }  =~ /^..$/ => matched.

Cette idiotie est tout parce que vous ne pouvez pas écrire le parfaitement raisonnable \u1F4A9, et bien sûr, vous ne recevez aucun avertissement que vous ne pouvez pas le faire. Cela fait juste la mauvaise chose.

Stoooopid.

Pendant que nous y sommes, la \uXXXXnotation entière est congénitalement morte de cerveau. Le préprocesseur Java ( oui, vous m'avez entendu ) y arrive avant Java, il vous est donc interdit d'écrire des choses parfaitement raisonnables comme "\u0022", car au moment où Java voit cela, son préprocesseur l'a transformé """, donc vous perdez. Oh attendez, pas si c'est dans une expression régulière! Vous pouvez donc utiliser "\\u0022"très bien.

Riiiiiiiight!

Saviez-vous qu'il n'y a aucun moyen en Java de faire un isatty(0)appel? Vous n'êtes même pas autorisé à penser de telles pensées. Ce ne serait pas bon pour toi.

Et puis il y a toute l'abomination du chemin de classe.

Ou le fait qu'il n'y a aucun moyen de spécifier l'encodage de votre fichier source Java dans ce même fichier source afin de ne pas le perdre? Encore une fois, je demande à savoir: QU'EN PENSENT-ILS?

Arrète la folie! Je ne peux pas croire que les gens supportent ces ordures. C'est une blague complète. Je préfère être un Walmart plus gourmand que de subir les frondes et les flèches de la folie scandaleuse de Java. Tout est cassé, et non seulement ils ne peuvent pas le réparer, ils ne le répareront pas.

Ceci par les mêmes personnes foxy-grapey qui se targuaient d'une langue qui rendait illégal d'avoir une printf()fonction. Gee, ça a très bien fonctionné, n'est-ce pas!?

Des crânes engourdis. La gifle est trop gentille pour eux. Si je voulais programmer en assembleur, je le ferais. Ce n'est pas une langue récupérable. L'empereur n'a pas de vêtements.

Nous le détestons. Nous le détestons pour toujours . Laissez-le mourir mourir mourir !


Haha, bien, je ne touche pas à Java parce qu'il est trop impoli comme tu le décris. Quant à \ uD83D ... eh bien je suppose qu'une meilleure façon de dire cela est que vous préférez que les chaînes ne soient pas UTF-16 mais UTF-32 à la place. Si vous acceptez UTF-16-ness, alors l'expression rationnelle fait ce qu'il faut; c'est l'appel de .length qui fout en l'air.
Roman Starkov

4
-1. À l'exception des commentaires d'expression régulière et des échappements Unicode, aucune des choses que vous avez mentionnées n'est un élément de syntaxe.
Jörg W Mittag

3
@ Jörg, tu veux la syntaxe? Très bien: Java vous permet de mettre des caractères de contrôle, y compris ESC et NUL, dans les identificateurs. A quoi pensaient-ils ???
tchrist

4
@tchrist: Wow! Si j'écris à nouveau un programme Java, toutes mes variables auront des noms composés d'un nombre variable de caractères de retour arrière ( ^H) :)
j_random_hacker

1
@tchrist, vous vous sentez mieux maintenant?

16

Syntaxe de déclaration du pointeur de fonction en C et C ++:

(int)(*f)(int, int);

Cela déclare un pointeur de fonction nommé fdont la pointe peut prendre deux ints et retourner un int.

Je préférerais de loin une syntaxe comme celle-ci:

f: (int, int) => int

Supposons que vous vouliez déclarer un pointeur de fonction gdont la pointe peut prendre deux ints et une fonction de intet intvers int, et renvoyer un int.

Avec la notation C ou C ++, vous le déclareriez comme:

(int)(*g)(int, int, int(int, int));

Avec la notation proposée ci-dessus, la même chose peut être déclarée comme:

g: (int, int, (int, int) => int) => int

Ce dernier est beaucoup plus intuitif IMO.


En plus: Le langage de programmation appelé OOC corrige cette syntaxe (et divers autres problèmes syntaxiques en C et C ++). Consultez sa page d'accueil ici .


D'accord, certains "plain C" / "C ++" ne le prennent pas en charge, ou le prennent en charge avec une syntaxe différente. Une syntaxe spéciale permet d'indiquer quand une fonctionnalité du langage de programmation est prise en charge. C'est pourquoi C # a ajouté la syntaxe "délégué".
umlcat

Les délégués ne sont pas seulement du sucre syntaxique car ils stockent également l'objet (contrairement aux pointeurs de fonction membre C ++, qui ont une syntaxe encore pire que les pointeurs de fonction réguliers)
Tamás Szelei

14

Verbosité en Java.

c'est à dire:

public static final int 

6
Par rapport à? (15 caractères)
TheLQ

7
Par rapport à: const intpar exemple.
OscarRyz

11
"public static final int x = 4;" par rapport à "x = 4" à Haskell.
Jared Updike

24
Ce n'est pas de la verbosité. Essayez d'écrire en a+(b*c)/d*e+f/g^20utilisant BigIntegeren Java. Pourquoi ce langage ne permet-il pas la surcharge de l'opérateur?
MAK

4
@Michael: les programmeurs qui ont besoin d'être protégés contre eux-mêmes à ce prix peuvent mieux se protéger (et réduire la douleur pour tout le monde) en ne programmant pas du tout: D.
MAK

12

\ we \ wouldnt \ fix \ our \ syntaxe de l'espace de noms de l'analyseur en PHP

La syntaxe n'est pas seulement laide, elle conduit à la confusion lorsque les nouveaux développeurs doivent penser aux espaces de noms dans les chaînes. (PHP interpole les barres obliques inverses dans les chaînes entre guillemets doubles en tant que séquences d'échappement. Essayer de représenter un espace de noms comme \you\should\never\do\thatdans une chaîne entre guillemets doubles au lieu d'une chaîne entre guillemets entraînera des sauts de ligne, des tabulations et un désastre.)


Oui, quelqu'un a pensé à une meilleure façon de faire cela, mais PHP insiste pour que chaque opérateur soit différent. Je suis curieux de savoir quel est le problème de l'utilisation abusive ici.
Alan Pearce, du

Se mettre d'accord. PHP nécessite des espaces de noms, mais cette syntaxe est un
problème

9

Je méprise le fait que les accolades peuvent être facultatives après une instruction if / while / for.

Surtout quand je vois du code comme,

if (...)
    for(...)
        ... One line of stuff ...

Veuillez simplement mettre les accolades et en finir.


6
Hmm .. cela dépend. Pour les "abandons Ifs" qui vérifient simplement une condition et renvoient un code d'erreur (ou lèvent une exception), je préfère de loin ne pas voir les accolades.
Billy ONeal

4
Je serais d'accord si vous vous limitez à des cas extrêmes à plusieurs niveaux, mais votre déclaration est trop générale. Il y a une grande utilité dans la possibilité d'avoir des formes courtes pour des ifs et des boucles simples à instruction unique.
Timwi

2
Ma règle: seulement si une instruction nécessite plusieurs sous-déclarations ou si elle contient une telle instruction doit être entourée d'accolades. Il for (...) while (...) if (...) { x(); y(); }est donc préférable de le réécrire comme for (...) { while (...) { if (...) { x(); y(); } } }, bien entendu, avec une indentation appropriée.
Jon Purdy

6
Je suis plutôt le contraire - je méprise les gens qui insistent pour mettre des accolades quand elles sont complètement inutiles. Apprenez simplement à programmer.
Jerry Coffin

3
J'aime vraiment les crochets, même dans les déclarations simples. Cela me permet de mieux suivre le déroulement d'un programme.
Ricardo Santos

9

VBScript n'a pas d'opérateurs logiques

Contrairement à presque tous les langages sensibles, VBScript utilise des opérateurs au niveau du bit au lieu des opérateurs logiques. Qu'est-ce que cela signifie dans la pratique? Eh bien, comme le souligne Eric Lippert :

If Blah = True Then Print "True!" Else Print "False!"

et

If Blah Then Print "True!" Else Print "False!"

ne sont PAS les mêmes dans VBScript!

Pire encore, cela signifie qu'il n'y a pas d'évaluation de court-circuit dans VBScript, de sorte que l'instruction suivante plantera votre programme s'il BlahestNothing

If (Not Blah Is Nothing) And (Blah.Frob = 123) Then
...

C'est vrai, VBScript évaluera les deux parties de la comparaison ET, même si la première est fausse! Laissez-le simplement pénétrer ...


3
Jusqu'au jour où vous avez chassé un bogue dans an If x Then ... If Not x Then ... End If ... End Ifet compris que x est 2, vous n'avez pas vraiment programmé en VB / VBScript.
configurateur

7

EDIT: Suite à la discussion dans les commentaires, j'ai décidé de mettre à jour cette réponse pour mieux m'expliquer.

Je déteste vraiment l'apparence des pointeurs de fonction en C. Habituellement, toute déclaration de variable ressemble à un tuple de: type varname; Les déclarations de pointeur de fonction, d'autre part, ressemblent à une déclaration de la fonction avec * avant le nom de la fonction. Je peux accepter cela comme une description d'un type de pointeur, mais en C, cela déclare à la fois le type et le nom d'une variable de ce type. Cela me semble incohérent car les déclarations de type sont par ailleurs distinctes des déclarations de variable. struct myStruct{int X; int Y;}définit uniquement un type, il ne définit pas une variable nommée myStruct. De même, je ne vois aucune raison pour que les déclarations de type et les déclarations de variables soient regroupées en une seule instruction atomique dans les pointeurs de fonction, et je n'apprécie pas non plus l'écart par rapport à la type varname;structure.

Quelqu'un a souligné que cela est cohérent avec une règle en spirale, et cela peut être le cas, mais la marque d'une bonne syntaxe est qu'elle s'explique d'elle-même et que sa logique interne est évidente. La règle en spirale n'est en aucun cas évidente.


1
Il est cohérent avec le reste du langage, alors peut-être que votre reproche concerne la syntaxe des déclarants C en général? Préférez-vous la syntaxe utilisée dans Go ?
finnw

Cohérent de quelle manière? Habituellement, cela va: tapez varname; Et lorsque nous créons un nouveau type composite, comme une structure, vient d'abord la déclaration, peut-être avec un typedef, puis nous créons une variable de ce type. Lorsque nous déclarons un pointeur de fonction, c'est int (* foo) (int arg1, int arg2), qui est ensuite utilisé comme type d'argument passé à une fonction: void newFoo (int (* foo) (int arg1, int art2 )) .... et comme variable: foo = a_compatible_func; Je pense qu'une déclaration de fonction d'abord, puis une déclaration var ensuite serait plus cohérente, comme ceci: typedef int (* foo) (int, int) MyFoo; MyFoo myfoo;
EpsilonVector du

Voilà pourquoi tu l'as typedef.
zneak

4
@EpsilonVector: J'ai tendance à convenir que la syntaxe du pointeur de fonction est désagréable, mais il existe une règle simple à suivre qui facilite la lecture. La règle en spirale dans le sens des aiguilles d'une montre (peut-être l'avez-vous vue?): C-faq.com/decl/spiral.anderson.html
greyfade

1
EpsilonVector: Je ne sais pas ce que vous attendez d'une déclaration de variable de pointeur pour déclarer autre que le nom de la variable.

6

Les points-virgules dans VBScript - ou leur absence

Je passe toute la journée à travailler dans des langues qui attendent des points-virgules à la fin de chaque ligne. Ajoutez-en un à la fin de la ligne dans VBScript et votre code ne s'exécute plus.


4
voter pour cela, non pas parce que j'aime particulièrement les points-virgules, mais parce que je déteste vraiment la façon dont VB encourage les très longues lignes en rendant les sauts de ligne si peu pratiques.
Shog9

6

Arguments d'entrée / sortie. Je suis pour les arguments (c'est une bonne chose que je sois), les arguments sont bien aussi, mais un argument qui doit transmettre ces deux états me fait chier.

Ce que je cible ici, ce sont les fonctions qui prennent l'entrée d'un paramètre puis écrasent cette entrée avec une sortie. Vous pouvez transmettre un objet par référence pour le mettre à jour. Mais, surtout pour les types primitifs, prendre un objet, l'utiliser, puis le changer complètement, ne me convient pas. Vous ne devez pas modifier la signification de l'argument par le biais d'une entrée.


Quelle langue avez-vous en tête? Si C #, je ne serais pas d'accord pour dire que c'est ennuyeux car il est toujours explicite (contrairement à C ++.) Je ne connais pas non plus de langage traditionnel où vous êtes obligé de déclarer des arguments comme in / out.
finnw

@finnw Je ne l' ai jamais vu une langue où vous aviez à dire inpour les inarguments non plus , je ne parle que d'eux. De plus, à mon avis, rien ne peut excuser un argument d'entrée / sortie, et les rendre explicites ne soulage pas la douleur. Il ne devrait y avoir aucune raison d'avoir à initialiser une variable locale avec une valeur utile à la fonction, et à ce que cette même variable contienne soudainement tout ce que la fonction a décidé d'y mettre. Ces deux devraient être distincts. Toujours.
zneak

Désolé, je n'étais pas très clair là-bas. Je voulais dire "Je ne connais pas de langue où tous les arguments sont implicitement entrants + sortants", c'est-à-dire que vous n'êtes pas obligé d'utiliser cette fonctionnalité, mais il existe des cas d'utilisation légitimes (par exemple, mettre à jour un structoù la nouvelle valeur dépend de la valeur d'un autre domaine de la même struct.)
finnw

@finnw Les objets passés par référence (comme les instances d' classobjets en C #) en cours de modification par une fonction me conviennent. Mis à part que je n'aime pas les structures non constantes, passer un structavec le refmot - clé pour le mettre à jour est également correct. Ce que je déteste vraiment, c'est quand l'entrée est remplacée par la sortie. Le meilleur exemple auquel je peux penser est la acceptfonction de la socket Berkeley : elle a besoin d'un socklen_t*argument qui, en entrée, doit contenir la taille de celle que struct sockaddr*vous avez passée; et en sortie, contiendra le nombre d'octets qui y ont été écrits. Cela devrait être criminel.
zneak

Je suis d'accord que c'est mauvais (IIRC certaines fonctions d'E / S Win32 font la même chose) mais c'est une mauvaise utilisation de la fonctionnalité (l'appel de fonction change la signification de la variable transmise, pas seulement sa valeur) et cela ne signifie pas la fonctionnalité lui-même est mauvais.
finnw

6

Déclarations de tableaux en C et C ++.

En règle générale, une déclaration de variable est au format type variable_name. Vous pouvez facilement lire ces déclarations de gauche à droite. Mais int foo[size]regarde d'abord comme si elle se déclarait foocomme un entier, puis vous lisez plus loin et voyez ces foo de type «tableau d'entiers». int[size] foolit beaucoup mieux.

Et je déteste aussi quand les programmeurs déclarent des pointeurs comme cela pour une raison similaire: int *foo. Pour une raison que je n'ai pas compris, c'est la façon typique dont c'est écrit.


1
Les déclarations de pointeur: elles sont écrites comme ça parce que le ' ' se lie au nom de la variable, pas au type. Ainsi int* a, b;* ne déclare pasa et bcomme pointeurs; seulement a. Il est donc préférable de l'écrire en tant que int *a, b;(ou encore mieux de les écrire en deux déclarations).
Steve Melnikoff

Bon point. C'est dommage *qu'il ne se lie pas au type.
Jacob

2
Et cela pour ne rien dire des pointeurs de fonction ... void(int) *f;? Non:void (*f)(int);
Note à moi-même - pense à un nom

Dans le C ++ moderne, il y a très peu de besoin de pointeurs et de tableaux.
fredoverflow

2
@Steve Melnikoff: Bien que j'aie attribué +1 à cette réponse, je pense que le int* a, b;problème que vous avez mentionné est beaucoup plus grave.
j_random_hacker

5

Paramétrage redondant en Java:

HashMap<String,HashMap<String,String>> foo = new HashMap<String, HashMap<String, String>>();

Quel autre type de paramétrage le compilateur pense foo -t-il avoir?


4
J'espère que vous êtes au courant de l'inférence de type Java (limitée)? HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
finnw

1
Java 7:HashMap<String,HashMap<String,String>> foo = new HashMap<>();
Bart van Heukelom

5
Eh bien, il peut avoir n'importe quel type, les types sont quand même effacés ...
configurateur

Manque d'inférence de type, tu veux dire?
missingfaktor

What other type parameterization does the compiler think foo could have?- Pour quelque raison que ce soit, c'est du type brut - comme si n'importe qui sain d'esprit mélangeait même des types bruts et paramétrés.
maaartinus

5

Étant donné que les gens se sont déjà plaints de =vs ==, permettez-moi de signaler une alternative bien pire. PL / J'avais les deux :=et =, mais quand quelque chose était "évidemment" une tâche, cela vous permettait de vous en passer =. L' utilisation :=vous permettant de forcer quelque chose à être une mission dans une situation où le compilateur autrement interpréter comme une comparaison.

Malheureusement, le compilateur n'a pas toujours décidé des choses comme vous pourriez vous y attendre. Prenons un exemple évident:

A = B = 0;

Maintenant, pour la plupart des gens familiers avec la plupart des langages "ordinaires", la signification de ceci est assez évidente - attribuer 0 à la fois à A et B. PL / I est juste un peu ... différent cependant. Pour des raisons connues des concepteurs (insensés) de la langue, la première =est interprétée comme une affectation, mais la seconde =est interprétée comme une comparaison. Par conséquent, cela compare B à 0, puis attribue le résultat de cette comparaison à A (conformément à la convention de style C selon laquelle "faux" donne 0 et "vrai" en 1).

Donc, si B était 0, alors A devient 1. Sinon, A devient 0. En d'autres termes, plutôt que d'attribuer la même valeur à A et B, cela garantit que A ne peut pas avoir la même valeur que B.

Bottom line: même si le style C / C ++ / PHP semble initialement difficile, l'alternative est bien pire 1 .

1 Eh bien, techniquement, il existe une autre alternative: le style Pascal, où =signifie toujours que la comparaison et l'affectation nécessitent toujours :=. Après l'avoir utilisé pendant un certain temps, il est assez évident (au moins pour moi) que l'affectation est suffisamment plus courante que la comparaison que si vous avez besoin de "trucs" supplémentaires pour lever l'ambiguïté des deux, vous devriez certainement garder les affectations propres et simples et exiger le "grunge" supplémentaire sur les comparaisons, et non l'inverse.


1
Je proposerais même d'utiliser ==pour l'égalité et :=pour l'affectation. De cette façon, vous avez plus à taper, mais éviter la solitude =aide à éviter les bugs.
maaartinus

@maartinus: au moins pour moi, cela ressemble à la pire possibilité absolue, mais telle est la vie ...
Jerry Coffin

3

Perl

  1. J'aimerais que Perl me laisse écrire if($x < 10) do_something();. Pour le moment, vous devez l'écrire soit comme, soit do_something() if($x < 10);comme if($x < 10) { do_something(); }.

9
do_something() if ($x < 10);n'est pas si mal.
zneak

Ce n'est pas le cas, et dans de nombreux cas, c'est beaucoup plus propre que if(..) ...de démarrer, car vous pouvez obtenir toutes les expressions à droite. Mais il y a des moments que je veux vraiment dire if($x < 10) do_something();, et c'est dommage que Perl ne me laisse pas.
Gaurav

7
C'est malheureux jusqu'à ce que vous écriviez if ($x<10) do_something(); and_call_me(); et que vous vous demandiez pourquoi vous ne recevez jamais d'appel. Je souhaite que C et sa famille aient besoin des accolades pour éviter ce type d'erreur.
AShelly

2
@AShelly: ou pourquoi vous recevez toujours un appel, en fait.
zneak

1
@zneak Sauf pas de elses. (Je souhaite qu'il ait EXPR1 if COND else EXPR2comme Python)
Ming-Tang

3

reinterpret_cast<unsigned long>en c ++. Cette opération est utile pour gérer les API étrangères et garantir la précision numérique, pourquoi devrait-il être si difficile de taper et si moche à regarder?


17
Il est moche de vous rappeler que vous devez vous efforcer d'écrire du code qui ne l'exige pas. :)
greyfade

Pour moi, c'est un bon argument théorique en informatique, mais d'après mon expérience, c'est trop utile pour éviter (Cependant, une grande partie de mon expérience est du vieux C ordinaire, j'ai donc probablement un biais).
AShelly

5
Ce n'est pas vraiment un argument CS théorique: l'utilisation d'un reinterpret_casten C ++ est une odeur de code très forte. 99% du temps, lorsque vous êtes sur le point de l'utiliser, il y a de fortes chances que vous ne deviez pas en avoir besoin - vous avez probablement fait quelque chose de mal. L'autre 1% du temps, vous vous connectez avec C. reinterpret_castcasse le système de type pour faire fonctionner quelque chose alors qu'il ne peut pas autrement. C'est généralement une mauvaise chose.
greyfade

3

La construction for ... in en JavaScript et la construction foreach en PHP lors du bouclage sur des tableaux. Les deux facilitent l'écriture de bogues que le code correct.


3
Wow, c'est une connerie. «Que le bon code». Allez-vous en.
Jonathan Sterling du

Si je dois écrire du code supplémentaire pour les utiliser en toute sécurité, ils sont plus faciles à utiliser mal dans mon livre. For ... in nécessite des vérifications supplémentaires pour vous assurer que vous n'itérez pas les objets du prototype, et foreach vous oblige à nettoyer les références par la suite ou risque d'écraser la dernière valeur du tableau.
Joeri Sebrechts

le foreach avec des références changeantes (& opérateur) est un bug célèbre ...
umlcat

1
Je suis confus, je pensais que tout le monde savait que la construction "for..in" en javascript est cassée ... pourquoi est-ce offensant?
lvilnis

2

Pointeurs de tableaux ou tableaux de pointeurs en C / C ++. Je suis toujours confus à ce sujet.


3
Lisez le type à l'envers. int[]*est un pointeur vers un tableau d'entiers, et int*[]est un tableau de pointeurs vers des entiers. Fonctionne bien avec consts aussi: int* constest un pointeur constant vers des entiers, tandis que const int*et int const*sont des pointeurs vers des entiers constants (ou vers des constantes entières).
zneak

@zneak: "De droite à gauche" ne fonctionne pas, voir la règle mentionnée "spirale dans le sens horaire" / "à l'envers" .

Ou, utilisez simplement des typedefs et il n'y a pas de confusion.
Billy ONeal

Dans le C ++ moderne, il y a très peu de besoin de pointeurs et de tableaux.
fredoverflow

4
@tchrist: Pas vrai. int (*p)[10];déclare pêtre un pointeur vers un tableau de 10 pouces. Si sizeof (int) == 4, alors p++avancera pde 40.
j_random_hacker


1

Javascript / Java etc, est égal à la comparaison, par exemple si (a == 1)

Combien de fois dois-je écrire si (a = 1)?

En tant qu'humain, je l'ai parfaitement lu. Mais l'interprète / compilateur sacrément dit: "hé je vais assigner 1 à a, puis vérifier si a est égal à 1, et le croiriez-vous oui c'est le cas!

Me conduit sur le mur.

si (a == 1) est beaucoup moins lisible, et l'interpréteur / compilateur devrait de toute façon savoir ce que je veux dire; de nombreuses autres langues moindres (VB) fonctionnent avec succès depuis des centaines d'années.


Qu'est-ce que c'est if (a = true)censé vouloir dire?
Tom Hawtin - tackline

2
L'affectation ne doit tout simplement pas renvoyer de valeur. C'est parfois utile, mais dans la plupart des cas, c'est juste une douleur dans le cou.
configurateur

en Javascript JSLint va attraper celui-là pour vous.
Zachary K

Le problème est que l'affectation dans des conditions peut être utile. Je trouve <tt> while (element = list-> next ()) </tt> assez lisible. Je ne suis donc pas sûr de vouloir le retirer.
Inca

3
@Tom: Cela signifie que vous ne comprenez pas les booléens. Si vous vouliez dire if (a == true), écrivez simplement if (a). Si vous vouliez dire a = true, alors la ifdéclaration est redondante.
dan04

1

Verbosité dans les classes anonymes Java. J'espère que ce problème sera bientôt corrigé.


À moins que vous ne vouliez plus d'une méthode.
Tom Hawtin - tackline

0

structPointer->memberen C / C ++. Peut être bon pour lire le code de quelqu'un d'autre, mais je n'aime pas ça. Deux personnages au lieu d'un ... quel gaspillage d'espace!


2
Malheureusement, il doit être distingué de ., qui s'applique aux membres d'un objet non pointeur. La syntaxe ambiguë est mauvaise, mmmkay?
greyfade

2
@greyfade: Ouais! Parce que le compilateur ne peut peut - être utiliser ses règles du système de type à dire lorsque vous utilisez un type pointeur à struct et appliquer le déréférencement implicitement. Non, c'est un discours fou! (Et pourtant, il peut toujours vous donner un message d'erreur lorsque vous vous trompez.) La syntaxe n'a rien d'ambigu. C'est juste que C est un gâchis de cervelle, comme d'habitude. Delphi fait des déréférences implicites très bien, si vous travaillez réellement dans des coins sombres qui nécessitent des pointeurs vers des enregistrements, donc cela peut certainement être fait sans confondre un analyseur ...
Mason Wheeler

5
@Mason: Qu'en est-il des cas tels shared_ptrque l' ->accès au type contenu et l' .accès aux propriétés de shared_ptrlui-même? Je suis désolé, mais je suis complètement en désaccord ici.
Billy ONeal

2
pourrait être pire. Cela pourrait être PHP, où vous devez utiliser ->pour accéder aux membres de n'importe quoi .
Carson Myers

1
@maaartinus: Tout code qui s'appuie autant sur un ordre d'opérations non évident n'est pas du code que j'écrirai.
Billy ONeal

0

Code multiligne Scala entre parenthèses

Par exemple:

class Foo(
         val bar: String,
         val baz: Int,
         val bing: String,
         val bong: Boolean
 ) extends Model {
   // body here
 }

Ce que vous en tirez est formidable. Il génère le constructeur et les getters et setters pour vous. Mais c'est vraiment moche et brise tous mes modèles mentaux sur la façon de mettre en retrait le code et me donne essentiellement l'impression d'être dans une sorte de sandwich bizarre avec Java d'un côté et Lisp de l'autre. (Oh, attendez ... c'est plutôt le but de Scala.)


Je suis confus - voulez-vous dire la partie entre parenthèses ( val baret ainsi de suite) ou la partie entre accolades (la partie suivante extends Model)? (Il n'y a pas de parenthèses dans ce code)
Billy ONeal

3
La partie entre parenthèses. Je suis Anglais. Nous les appelons entre parenthèses, putain, parce que dans cette situation, ils ne jouent pas un rôle entre parenthèses.
Tom Morris

2
Cela ne semble pas si mal si indenté de cette façon: pastebin.com/h9qC8XGg
missingfaktor

Je trouve plus lisible d'écrire ces listes de paramètres de constructeur horizontalement, surtout quand je n'ai que quelques paramètres.
MJP

Cela ressemble à une méthode pour moi. Comme Simula. Bonne vieille école.
Tom Hawtin - tackline
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.