Quale elemento di sintassi odi di più in un linguaggio di programmazione che usi frequentemente? [chiuso]


27

Non importa quanto ami un linguaggio di programmazione, ci sono sempre alcuni dettagli che non sono così belli come potrebbero essere.

In questa domanda, vorrei concentrarmi specificamente sugli elementi di sintassi. In un linguaggio di programmazione che usi frequentemente (forse il tuo linguaggio di programmazione preferito, o forse quello che sei costretto a usare al lavoro), quale elemento di sintassi trovi più illeggibile, poco chiaro, scomodo o spiacevole?


@Nathan Taylor, non per questa domanda, ma per un'altra domanda .
Finnw,

Questa domanda è stata modificata? Perché quando ho risposto, non era focalizzato su "elementi di sintassi" ... Ora dovrò modificare la mia risposta.
Talvi Watia,

@Talvi: No, si trattava di sintassi sin dall'inizio.
Timwi,

@Timwi strano, deve essere un caso di "rispondere a una domanda pensando che fosse diverso" allora.
Talvi Watia,

Se puoi votare e pensare che questa sia una domanda utile o abbia delle risposte utili di seguito, vota per favore. I siti StackExchange hanno bisogno di voti per costruire una buona comunità. Puoi dare 30 voti al giorno, non sprecarli. Specialmente gli utenti con alta reputazione e basso numero di voti assegnati si prega di leggere questo: meta.programmers.stackexchange.com/questions/393/…
Maniero

Risposte:


39

Inserimento punto e virgola in JavaScript.

Non mi è mai stato morso spesso, ma è un'idea così fenomenale che mi fa girare la testa.


Ecco le regole (da ECMA-262 Sezione 7.9)

  1. Quando il programma contiene un token che non è consentito dalla grammatica formale, viene inserito un punto e virgola se (a) c'è un'interruzione di linea in quel punto, o (b) il token imprevisto era un controvento di chiusura.
  2. Quando viene raggiunta la fine di un file, se il programma non può essere analizzato diversamente, viene inserito un punto e virgola.
  3. Quando viene rilevata una "produzione limitata" e contiene un terminatore di riga in un punto in cui la grammatica contiene l'annotazione "[nessun LineTerminator qui]", viene inserito un punto e virgola.

Esempio:

return 1; // returns 1

return
1; // returns undefined

2
JavaScript: il linguaggio di programmazione più frainteso al mondo ~ Douglas Crockford
pramodc84

Sì, molti si aspettano che JavaScript sia un "linguaggio in formato libero", ma non lo è.
Andreas Rejbrand,

13
Ha senso quando ti rendi conto che JavaScript è stato progettato per la creazione di HTML, che ha anche una lunga storia nel tentativo di interpretare ciò che il tuo codice "significa veramente" quando non è sintatticamente valido. (Consulta il principio di robustezza qualche volta - il più grande disastro nella storia dell'informatica.)
Mason Wheeler,

7
Questi tipi di errori, per me, sono un odore di codice secondo cui il programmatore è sciatto e non ha mai lavorato con la maggior parte dei linguaggi "rigorosi" formali che normalmente causerebbero un errore di sintassi per lasciare fuori il punto e virgola.
Talvi Watia,

7
Wohoo, finalmente qualcun altro che pensa anche che il principio di robustezza sia un disastro che ha reso l'HTML il vero casino che è.
Roman Starkov,

39

Sintassi del bean Java a causa della mancanza di proprietà 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 !!!

Problemi che ho con questo

  • Troppo codice - Avere un campo documentato, un metodo getter documentato e un metodo setter documentato. Questo esempio estremamente semplice ha 20 righe di codice per una singola proprietà
  • Elenchi di metodi Clutters - "Fammi trovare quel metodo, mano su:getX , getY, getZ, getAnotherAnnoyingField, getWhyIHateJavaBeans, getThisIsVerbose, getGAH... ah eccolo, hashCode.
  • Molteplici aree di documentazione portano a documentazione scadente, obsoleta o mancante : fastidioso quando si cerca di capire cosa fa il codice
  • Quindi una fastidiosa terza parte ha dovuto inventare un plugin per farlo facilmente - Spoon , Shark , tra gli altri.

9
Ancora una volta quando il codice è così dettagliato da richiedere strumenti di generazione automatica, qualcosa non va. Sono un ragazzo di NetBeans, ma ha anche la capacità di generare automaticamente getter e setter. Ma Javadoc non è più sincronizzato, è ancora dettagliato, ingombra ancora javadoc, ecc.
TheLQ

11
Se hai bisogno di getter per tutto, allora qualcosa non va nel codice client .
Finnw,

7
Avere getter e setter rompe l'incapsulamento. Il campo potrebbe anche essere public. I membri dovrebbero essere privati ​​e dovrebbero essere manipolati sensibilmente dalla classe con una logica di livello superiore, non con getter e setter dal codice client.
Greyfade,

6
@greyfade: se è pubblico, non puoi cambiare facilmente il codice di impostazione (dovrai cambiare tutto il codice che imposta il campo dall'esterno).
Bart van Heukelom,

3
@SHiNKiROU: Java sembra pulito? Non l'ho mai sentito prima! La mia lamentela principale con Java è il fatto che una cosa apparentemente semplice prende dozzine di righe di codice che devo ignorare mentalmente.
configuratore

33

Sensibilità agli spazi bianchi.

Python mi infastidisce in questo senso. Voglio dire, rientro correttamente comunque, ma mi dà fastidio che avrei dovuto . Rendere la presentazione parte della sintassi mi irrita.


8
imparerai ad amarlo
user10008

2
la sintassi è presentazione
Winston Ewert

32

La switchdichiarazione (in C, C ++, C #, Java, ecc.)

Ecco un esempio del perché lo trovo estremamente scomodo:

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

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

Questo non viene compilato perché la variabile iviene rideclared nello stesso ambito. Sembra un dettaglio minore, ma mi morde molto spesso. Posso aggiungere parentesi graffe per mitigarlo, ma sarebbe bello se le parentesi graffe fossero state parte obbligatoria della sintassi e non vi fosse alcun livello di ridondanza aggiuntivo ridondante. Odio anche dover scrivere un extra break. Questo sarebbe molto più bello:

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

Questo lo rende più simile a una if/ elsecatena, il che è una buona cosa perché è anche semanticamente simile. Almeno in C # non sarebbe comunque la stessa cosa, perché in una switchdichiarazione l'ordine delle etichette del caso non ha importanza, ma in un if/ elselo fa.


1
Sfortunatamente, la tua sintassi migliorata elimina quella che è, probabilmente, la più grande funzionalità di switch nella maggior parte di queste lingue: Fall-through. "Duff's Device" in C è un perfetto esempio del valore di questa particolare "caratteristica errata". È anche comune nei linguaggi di tipo C usare il fall-through in interpreti e programmi simili.
Greyfade,

7
No, non lo elimina. Richiede solo che sia reso più esplicito (usando uno gotoo simile), come già accade in C #.
Timwi,

8
@greyfade: qualsiasi codice che utilizza il dispositivo di Duff in C deve morire in modo orribile. I compilatori prendono decisioni migliori su questo tipo di cose rispetto a te.
Billy ONeal,

4
@greyfade: Delphi aggira il problema valore multiplo semplicemente consentendo più indici nel caso: case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;.
Frank Shearar,

3
@jkerian: ora immagina che breakfosse l'impostazione predefinita e che è stato necessario specificare solo il fallthrough. Non è più necessario ricordare di commentarlo! :)
Timwi,

27

Dichiarazioni di array in VB.NET

Riesco sempre a dimenticare che quando si inizializzano array fissi in VB.NET, si specifica il limite superiore dell'array e non il numero di elementi come in C / C ++, PHP o Java. Oltre a VB6 (non andremo lì ...), non riesco a pensare a un'altra lingua che lo fa in questo modo:

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

Penso che tutte le lingue BASIC lo facciano ... So che sono BASIC e QBasic originali.
Michael K,

OMG che è davvero orribile .... +1
Mikera,

25

VB6 - Dichiarazione e assegnazione variabili separate

La maggior parte delle lingue ti consente di dichiarare una variabile e assegnarla in una riga di codice; VB6, d'altra parte, ti costringe a usarne due.

Dim i as Integer
i = 0

Dim derpderp as Collection
Set derpderp = new Collection

È possibile utilizzare i due punti per inserire due comandi su una riga, ma diventa rapidamente disordinato nel codice reale.

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

7
+1 per dover usare VB6 come lingua più frequente.
Walter,

9
Lo uso quotidianamente ... sob.
systempuntoout

Pascal non ha una sintassi simile? Ho sempre pensato che fosse brutto.
Greyfade,

1
C'è un caso speciale: se Dim Hurp As New Collectionaccedete Hurpquando vi si riferisce Nothing, verrà magicamente inizializzato prima dell'accesso. Se lo imposti esplicitamente Nothinge lo tocchi di nuovo, viene resuscitato ... sussulto!
Jeffrey Hantin,

1
+ 1 milione per Derp. Derp de derp de tiddly tum de derp.
MVCylon,

24

Commentando in CSS

//non commenta righe di codice come in molte altre lingue, come PHP e Javascript. Anche se /* this is commented out */funziona, preferisco usare// .

È un fastidio, perché la metà delle volte mi dimentico che sto modificando CSS e quindi devo tornare indietro e correggere l'errore.


In questi giorni avresti pensato che i CSS grezzi sarebbero stati considerati codice oggetto.
Tom Hawtin - tackline

// funziona perfettamente per commentare CSS. Lo faccio tutto il tempo. Tutto quello che sto davvero facendo è digitare spazzatura. ma sembra funzionare saltando la linea non analizzabile.
MVCylon,

1
@MVCylon Se si utilizza // per commentare una riga, viene saltato anche tutto ciò che segue quella riga successiva. {all'interno di quello stile specifico} In altre parole, GUASTA perché quelle linee non devono essere saltate.
Talvi Watia,

20

PHP - ordinamento coerente degli argomenti

PHP ha una serie di utili funzioni per eseguire praticamente ogni operazione che si possa pensare su un array o una stringa. Molte di queste operazioni richiedono l'utilizzo sia di una $needleche di una $haystack, ma funzioni diverse le portano in ordini diversi. Quale funzione richiede quali argomenti sono uno di quei fatti che il mio cervello rifiuta di assorbire, non importa quante volte li incontro!

Prendi le funzioni in_array e 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])

Stranamente, PHP sembra essere internamente coerente con questi ordinamenti in quanto tutte le funzioni di stringa sembrano usare $haystack, $needlementre le funzioni di matrice sono il contrario, ma questo può richiedere un po 'di tempo per abituarsi a qualcuno che non conosce PHP. C'è un buon post su ExpressionEngine che parla di questa particolare stranezza in modo più dettagliato, così come una discussione sulla lista dei bug di PHP , che presenta una risposta molto breve da parte del team PHP!

helly@php.net
Usa quindi un IDE decente.

2
È più facile ricordare l'ordine $needle, $haystackin quanto ricorda il modo di dire trovare un ago in un pagliaio .
kiamlaluno,

3
Protip: nelle funzioni array, l'ago viene prima di tutto. nelle funzioni stringa, il pagliaio viene prima di tutto.
GSto

17
Adoro il nome strstr. Così meravigliosamente insignificante.
configuratore

5
Basta leggere la voce collegata nel bugtracker di PHP. Davvero, wtf? oO La coerenza di Imho è un problema valido per qualsiasi API e solo rispondere con "usa un IDE decente" non è una risposta valida. Almeno avrebbe potuto essere definito meno infiammatorio dagli sviluppatori.
Baelnorn,

2
Onestamente, ciò che mi fa impazzire è che non dovrebbe essere affatto una funzione! Dovrebbe essere solo un metodo: $ pagliaio-> trova ($ ago). Affare fatto.
riwalk

19

Pitone

self parametro nelle definizioni del metodo di istanza


In un metodo di classe, di solito si chiama cls e l'uso di sé va contro la convenzione.

In realtà ha senso se ci pensate. È lo stesso che dichiarare un metodo privato in altre lingue, il parametro personale è esplicito in Python dove è implicito in altre lingue. Se vuoi che sia implicito aggiungi il decoratore @classmethod prima della dichiarazione del metodo. Vedi docs.python.org/library/functions.html#classmethod . Imparare i dettagli di come funziona ti darà un'idea di come è stato fatto implicitamente in altre lingue.
Evan Plaice,

4
Capisco i motivi e perché è rimasto lì neopythonic.blogspot.com/2008/10/… ma ancora non mi piace
Goran Peroš

@Evan Plaice: 'L'auto-parametro è esplicito in Python dove è implicito in altre lingue' Questa è solo una parte della storia. L'altra parte è che Python viene digitato settimanalmente. Insieme è terribile, dimenticare selffacilmente e costa tempo.
maaartinus,

@maaartinus Quindi aggiungi un decoratore di metodi di classe ai tuoi metodi di istanza. Non ha nulla a che fare con "debolmente tipizzato". Rende evidente la relazione tra metodi / funzioni statici (nessun parametro "self") e metodi di istanza (include "self"). Un metodo di istanza non è a conoscenza della sua classe genitore a meno che tu non gli dia un riferimento per farlo. In altre lingue la caratteristica distintiva che ho delineato è appena nascosta dietro lo zucchero sintattico. Se avessi avuto la possibilità di fare tutto da capo avrei iniziato a studiare OOP in Python prima.
Evan Plaice,

18

Giava

Periodo. Punto. Fine della storia.

Dove iniziare? Oh, so da dove cominciare: i generici follemente complicati, brutti, stupidi e intrinsecamente rotti . Devo aggiungere altro? :( Va bene, quindi: digita cancellazione .

Quindi c'è una gestione delle risorse non deterministica. Kewl feetcher!

Qual è il prossimo passo? Oh sì: le stupide regex di Java sono la mia carne più irritante e ribollente. Non riesco a contare quante volte sono stato colpito dal fatto che non ho abbastanza barre rovesciate. Questo è anche peggio che non avere accesso a nessuna proprietà Unicode di questo millennio - che è un toro completo. Dieci anni da baraccone fuori moda !!!Completamente inutile. Trash it.

Quindi c'è il bug che le scorciatoie della classe di caratteri non funzionano su non ASCII. Che dolore reale! E non considerare nemmeno l'utilizzo\p{javaWhiteSpace} ; non fa la cosa giusta con diversi punti di codice di spazi bianchi Unicode molto comuni.

Sapevi che c'è una \p{javaJavaIdentifierStart}proprietà? Che cosa stavano pensando? Sono così contento di aver fatto sbirciare così furbi su questo disco.

Hai mai provato a usare il flag CANON_EQ? Lo sai che lo fa davvero e cosa non fa? Che ne dici del cosiddetto "caso Unicode"? Un sacco di cose normali del case non funzionano affatto.

Quindi rendono difficile scrivere regex mantenibili. Java non ha ancora capito come scrivere stringhe multilinea, quindi finisci per scrivere cose folli come questa:

    "(?= ^ [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" 

Cosa sono tutte quelle nuove linee? Oh, solo stupidità di Java. Hanno usato commenti Perl, non commenti Java ( idioti! ) Che vanno fino alla fine della riga. Quindi se non li metti\n lì, taglia il resto del tuo schema. Duh e double duh!

Non usare regex in Java: finirai per voler distruggere le cose, è tutto così doloroso e rotto. Non posso credere che la gente lo sopporti. Alcuni no .

Quindi possiamo iniziare a parlare dell'assurdità idiota di Java con le codifiche. Innanzitutto, c'è il fatto che la codifica della piattaforma predefinita è sempre una codifica a 8 bit scadente anche se i charchar di Java sono Unicode. Quindi c'è come non generano un'eccezione su un errore di codifica. Ti garantirai una merda. O che ne dici di questo:

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.

Qual è la differenza? Lo sapevi solo uno di questi genererà un'eccezione se si verifica un errore di codifica? Il resto li mette solo a museruola.

Poi c'è l'idiozia dei caratteri Java che non sono sufficienti per contenere un personaggio! A che diavolo stanno pensando? Ecco perché li chiamo charchars. Devi scrivere codice in questo modo se ti aspetti che funzioni correttamente:

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("."); }
    }
}

E chi mai pensa di farlo? Accanto a nessuno.

In quanti personaggi ci sono "\uD83D\uDCA9"? Uno o due? Dipende da come li conti. Il motore regex si occupa ovviamente dei caratteri logici, quindi un modello ^.$avrà successo e un modello ^..$fallirà. Questa follia è dimostrata qui:

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.

Quell'idiota è tutto perché non puoi scrivere il perfettamente ragionevole \u1F4A9 , e naturalmente non ricevi alcun avviso sul fatto che non puoi farlo. Fa solo la cosa sbagliata.

Stoooopid.

Mentre ci siamo, l'intera \uXXXXnotazione è congenitamente cerebrale. Il preprocessore Java ( sì, mi hai sentito ) ci arriva prima che lo faccia Java, quindi ti è proibito scrivere cose perfettamente ragionevoli come "\u0022", perché quando Java lo vede, il suo preprocessore lo ha trasformato """, quindi perdi. Oh aspetta, non se è in una regex! Quindi puoi usare"\\u0022" bene.

Riiiiiiiight!

Sapevi che in Java non c'è modo di farlo isatty(0) chiamata? Non ti è nemmeno permesso di pensare tali pensieri. Non ti farebbe bene.

E poi c'è l'intero abominio del sentiero di classe.

O il fatto che non c'è modo di specificare la codifica del file sorgente Java nello stesso file sorgente in modo da non perderlo? Ancora una volta chiedo di sapere: COSA PENSANO L'INFERNO?

Ferma la follia! Non riesco a credere che la gente sopporti questa spazzatura. È uno scherzo completo. Preferirei essere un salutista Walmart piuttosto che subire le imbragature e le frecce della folle follia di Java. È tutto rotto e non solo non possono ripararlo, non lo ripareranno.

Questo dalle stesse persone volgari che si vantavano di un linguaggio che rendeva illegale avere una printf()funzione. Accidenti, quello certo ha funzionato davvero bene, non è vero però !?

Teschi di numeri. Gli schiaffi sono troppo gentili per loro. Se volessi programmare in assembler, lo farei. Questo non è un linguaggio salvabile. L'imperatore è nudo.

Lo odiamo. Lo odiamo per sempre . Lascialo morire muori muori !


Haha, bravo, non tocco java perché è troppo non lucidato come descrivi. Per quanto riguarda \ uD83D ... beh, suppongo che un modo migliore di dire questo è che preferiresti che le stringhe non fossero UTF-16 ma UTF-32 invece. Se accetti UTF-16-ness allora il regex fa la cosa giusta; è la chiamata .length che fa schifo.
Roman Starkov,

4
-1. Ad eccezione dei commenti regexp e delle escape Unicode, non una sola delle cose che hai menzionato è un elemento di sintassi.
Jörg W Mittag,

3
@ Jörg, vuoi la sintassi? Ok bene: Java ti consente di inserire i caratteri di controllo, inclusi ESC e NUL, negli identificatori. A cosa stavano pensando ???
tchrist,

4
@tchrist: Wow! Se dovessi mai scrivere di nuovo un programma Java, tutte le mie variabili avranno nomi costituiti da un numero variabile di caratteri backspace ( ^H) :)
j_random_hacker

1
@tchrist, ti senti meglio adesso?

16

Sintassi della dichiarazione del puntatore a funzione in C e C ++:

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

Che dichiara un puntatore a funzione chiamato il fcui punta può richiedere due intsecondi e restituire un int.

Preferirei di gran lunga una sintassi come questa:

f: (int, int) => int

Supponiamo che tu voglia dichiarare un puntatore a funzione la gcui punta può prendere due se intuna funzione da inte inta int, e restituire un int.

Con la notazione C o C ++, la dichiareresti come:

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

Con la notazione sopra proposta la stessa cosa può essere dichiarata come:

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

Ultimamente l'IMO è molto più intuitivo.


A parte: il linguaggio di programmazione chiamato OOC risolve questa sintassi (e vari altri problemi sintattici in C e C ++). Dai un'occhiata alla sua homepage qui .


D'accordo, alcuni "semplici C" / "C ++" non lo supportano, né lo supportano con sintassi diversa. Una sintassi speciale, aiuta a indicare quando è supportata una funzione del linguaggio di programmazione. Ecco perché C # ha aggiunto la sintassi "delegata".
Umlcat,

I delegati non sono solo zucchero sintattico perché immagazzinano anche l'oggetto (contrariamente ai puntatori di funzione membro C ++, che hanno una sintassi ancora peggiore rispetto ai normali puntatori di funzione)
Tamás Szelei,

14

Verbosità in Java.

vale a dire:

public static final int 

6
Rispetto a? (15 caratteri)
TheLQ

7
Rispetto a: const intper esempio.
OscarRyz,

11
"public static final int x = 4;" rispetto a "x = 4" in Haskell.
Jared Updike,

24
Questa non è verbosità. Prova a scrivere a+(b*c)/d*e+f/g^20usando BigIntegerin Java. Perché questa lingua non consente il sovraccarico dell'operatore?
MAK,

4
@Michael: i programmatori che hanno bisogno di essere protetti da se stessi a questo costo possono proteggere meglio se stessi (e ridurre il dolore per tutti gli altri) non programmando affatto: D.
MAK,

12

Sintassi dello spazio dei nomi \ we \ wouldnt \ fix \ our \ parser in PHP

La sintassi non è solo brutta, porta alla confusione quando i nuovi sviluppatori devono pensare agli spazi dei nomi nelle stringhe. (PHP interpola le barre rovesciate in stringhe tra virgolette doppie come sequenze di escape. Cercare di rappresentare uno spazio dei nomi come \you\should\never\do\thatin una stringa tra virgolette doppie anziché in una stringa tra virgolette singole porta a nuove righe, tabulazioni e disastri.)


Sì, qualcuno ha pensato a un modo migliore per farlo, ma PHP insiste sul fatto che ogni operatore deve essere diverso. Sono curioso di sapere quale sia il problema dell'abuso qui.
Alan Pearce,

Essere d'accordo. PHP richiede spazi dei nomi, ma quella sintassi lo
rovina

9

Disprezzo il fatto che le parentesi graffe possano essere opzionali dopo un'istruzione if / while / for.

Soprattutto quando vedo codice come,

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

Per favore, metti le parentesi graffe e finiscila.


6
Hmm .. questo dipende. Per "Abort Ifs" che controlla semplicemente una condizione e restituisce un codice di errore (o genera un'eccezione), preferirei di gran lunga non vedere le parentesi graffe.
Billy ONeal,

4
Sarei d'accordo se ti limitassi a casi multilivello estremi, ma la tua affermazione è troppo generale. Vi è una grande utilità nella capacità di avere forme brevi per if e loop semplici a singola istruzione.
Timwi,

2
La mia regola: solo se un'istruzione richiede più sostituzioni o se contiene un'istruzione simile dovrebbe essere racchiusa tra parentesi graffe. Quindi for (...) while (...) if (...) { x(); y(); }è meglio riscritto come for (...) { while (...) { if (...) { x(); y(); } } }, con il rientro appropriato, ovviamente.
Jon Purdy,

6
Sono piuttosto l'opposto: disprezzo le persone che insistono nel mettere le parentesi graffe quando sono completamente inutili. Basta imparare a programmare.
Jerry Coffin,

3
Mi piacciono molto le parentesi quadre anche nelle singole istruzioni if. Mi fa seguire meglio il flusso di un programma.
Ricardo Santos,

9

VBScript non ha operatori logici

A differenza di quasi tutti i linguaggi sensibili, VBScript utilizza operatori bit per bit anziché operatori logici. Cosa significa in pratica? Bene, come sottolinea Eric Lippert :

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

e

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

NON sono gli stessi in VBScript!

Ancora peggio, tuttavia, ciò significa che non esiste una valutazione di cortocircuito in VBScript in modo che la seguente istruzione arresti il programma in modo anomalo se BlahèNothing

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

Esatto, VBScript valuterà entrambe le parti del confronto AND, anche se il primo è falso! Lascia che affondi quel ...


3
Fino al giorno in cui hai cacciato un bug all'interno di un If x Then ... If Not x Then ... End If ... End Ife hai capito che x è 2, non hai davvero programmato in VB / VBScript.
configuratore

7

EDIT: dopo la discussione nei commenti ho deciso di aggiornare questa risposta per spiegarmi meglio.

Odio davvero il modo in cui i puntatori a funzione appaiono in C. Di solito qualsiasi dichiarazione di variabile sembra una tupla di: type varname; Le dichiarazioni dei puntatori a funzione invece sembrano una dichiarazione della funzione con * prima del nome della funzione. Posso accettarlo come descrizione di un tipo di puntatore, ma in C questo dichiara sia il tipo che il nome di una variabile di quel tipo. Questo mi sembra incoerente perché le dichiarazioni dei tipi sono altrimenti distinte dalle dichiarazioni delle variabili. struct myStruct{int X; int Y;}definisce solo un tipo, non definisce una variabile denominata myStruct. Allo stesso modo non vedo alcun motivo per raggruppare le dichiarazioni di tipo e le dichiarazioni di variabili in un'unica istruzione atomica in puntatori a funzione, né apprezzo la deviazione daltype varname; struttura.

Qualcuno ha sottolineato che è coerente con qualche regola a spirale, e potrebbe essere il caso, ma il segno di una buona sintassi è che si spiega da sé e la sua logica interna è ovvia. La regola della spirale non è affatto ovvia.


1
È coerente con il resto della lingua, quindi forse la tua lamentela riguarda la sintassi dei dichiaranti C in generale? Preferisci la sintassi usata in Go ?
finnw,

Coerentemente in che modo? Di solito va: digitare varname; E quando creiamo un nuovo tipo composito, come una struttura, prima arriva la dichiarazione, magari con un typedef, e quindi creiamo una variabile di quel tipo. Quando dichiariamo un puntatore a funzione, è int (* foo) (int arg1, int arg2), che viene quindi utilizzato come tipo di argomento passato a una funzione: void newFoo (int (* foo) (int arg1, int art2 )) .... e come variabile: foo = a_compatible_func; Penso che prima una dichiarazione di funzione e poi una dichiarazione var sarebbe più coerente, in questo modo: typedef int (* foo) (int, int) MyFoo; MyFoo myfoo;
Epsilon,

Ecco perché l'hai ottenuto typedef.
zneak,

4
@EpsilonVector: tendo a concordare sul fatto che la sintassi del puntatore a funzione è cattiva, ma c'è una semplice regola da seguire che rende più facile la lettura. La regola della spirale in senso orario (forse l'hai vista?): C-faq.com/decl/spiral.anderson.html
greyfade

1
EpsilonVector: Non sono sicuro di cosa ti aspetteresti da una dichiarazione di variabile puntatore per dichiarare diverso dal nome della variabile.

6

Punto e virgola in VBScript - o la loro mancanza

Passo tutto il giorno a lavorare in lingue che prevedono punti e virgola alla fine di ogni riga. Aggiungine uno alla fine della riga in VBScript e il tuo codice non verrà più eseguito.


4
voto positivo, non perché mi piacciono particolarmente i punti e virgola, ma perché odio davvero il modo in cui VB incoraggia le linee molto lunghe rendendo le interruzioni di riga così scomode.
Shog9

6

Argomenti in / out. Sono tutto per argomenti (per fortuna lo sono), anche gli argomenti vanno bene, ma un argomento che deve trasmettere questi due stati mi fa incazzare.

Quello che mi rivolgo qui sono funzioni che prendono l'input da un parametro e poi lo sovrascrivono con un po 'di output. Va bene passare un oggetto per riferimento per aggiornarlo. Ma, soprattutto per i tipi primitivi, prendere un oggetto, usarlo, quindi cambiarlo completamente, non è giusto per me. Non dovresti cambiare il significato dell'argomento attraverso un inout.


Che lingua hai in mente? Se C # non sarei d'accordo sul fatto che sia fastidioso perché è sempre esplicito (diversamente dal C ++). Inoltre non conosco alcun linguaggio tradizionale in cui sei costretto a dichiarare gli argomenti come in / out.
finnw,

@finnw Non ho mai visto una lingua in cui si doveva dire inper inargomenti o, sto solo parlando di loro. Inoltre, secondo me, nulla può giustificare un argomento in / out, e renderli espliciti non allevia il dolore. Non ci dovrebbero essere motivi per inizializzare una variabile locale con un valore utile alla funzione e avere questa stessa variabile quindi contenere improvvisamente qualunque cosa la funzione abbia deciso di inserire. Questi due dovrebbero essere distinti. Sempre.
zneak,

Mi dispiace non ero molto chiaro lì. Intendevo dire "Non conosco nessun linguaggio in cui tutti gli argomenti siano implicitamente in + out", cioè non sei obbligato a utilizzare quella funzione, ma ci sono casi d'uso legittimi (ad esempio l'aggiornamento di un structdove il nuovo valore dipende dal valore di un altro campo dello stesso struct.)
finnw,

@finnw Per me gli oggetti passati per riferimento (come istanze di classoggetti in C #) modificati da una funzione. A parte che non mi piacciono le strutture non costanti, anche passare una structcon la refparola chiave per aggiornarla va bene. Quello che odio davvero è quando l'input viene sovrascritto con l'output. Il miglior esempio che mi viene in mente è la acceptfunzione del socket Berkeley : ha bisogno di un socklen_t*argomento che, in input, deve contenere la dimensione del struct sockaddr*tuo passaggio; e in output, conterrà il numero di byte che sono stati scritti su di esso. Questo dovrebbe essere criminale.
zneak,

Sono d'accordo che è male (IIRC alcune funzioni I / O Win32 fanno lo stesso) ma che è un uso improprio della funzione (la chiamata di funzione cambia il significato della variabile passata, non solo il suo valore) e non significa la funzionalità è di per sé cattivo.
finnw,

6

Dichiarazioni di array in C e C ++.

In genere, una dichiarazione variabile è del formato type variable_name. Puoi facilmente leggere quelle dichiarazioni in modo da sinistra a destra. Ma int foo[size]dapprima sembra che stia dichiarando foocome un int, e poi leggi più avanti e vedi che il foo è di tipo "array di numeri interi". int[size] foolegge molto meglio.

E ho anche odio quando i programmatori dichiarano puntatori come questo per un motivo simile: int *foo. Per qualche motivo non l'ho capito, è il modo tipico in cui è scritto.


1
Dichiarazioni relative al puntatore: sono scritte in questo modo perché " " si lega al nome della variabile, non al tipo. Quindi int* a, b;* non dichiara ae bcome puntatori; lo aè solo . Quindi è meglio scriverlo come int *a, b;(o anche meglio scriverli come due dichiarazioni).
Steve Melnikoff,

Buon punto. È un peccato che *non si leghi al tipo.
Jacob,

2
E questo per non parlare dei puntatori a funzioni ... void(int) *f;? No:void (*f)(int);
Nota per se stessi - pensa a un nome il

Nel C ++ moderno c'è pochissima necessità di puntatori e matrici.
fredoverflow,

2
@Steve Melnikoff: Anche se ho fatto +1 su questa risposta, penso che il int* a, b;problema che hai citato sia molto più evidente.
j_random_hacker,

5

Parametrizzazione ridondante in Java:

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

Quale altra parametrizzazione di tipo pensa foo possa avere il compilatore ?


4
Spero che tu sia a conoscenza dell'inferenza del tipo (limitato) di Java? HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
Finnw,

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

5
Beh, può avere qualsiasi tipo voglia, i tipi vengono comunque cancellati ...
configuratore

Mancanza di inferenza di tipo, vuoi dire?
missingfaktor,

What other type parameterization does the compiler think foo could have?- Per qualunque motivo, è di tipo grezzo - come se qualcuno fosse sano di mente mescolerebbe anche tipi grezzi e parametrizzati.
maaartinus,

5

Dato che le persone si sono già lamentate di =vs. ==, vorrei far notare un'alternativa molto peggiore. PL / Avevo entrambi :=e =, ma quando qualcosa era "ovviamente" un compito, ti avrebbe permesso di cavartela =per farlo. utilizzando:= ti permetti di forzare qualcosa ad essere un compito in una situazione in cui il compilatore lo interpreterebbe come un confronto.

Sfortunatamente, il compilatore non ha sempre deciso le cose esattamente come ci si potrebbe aspettare. Considera solo un esempio ovvio:

A = B = 0;

Ora, per la maggior parte delle persone che hanno familiarità con la maggior parte delle lingue "ordinarie", il significato di questo è abbastanza ovvio: assegnare 0 sia a A che a B. PL / I è solo un po '... diverso. Per ragioni note solo ai (folli) designer del linguaggio, il primo =viene interpretato come un incarico, ma il secondo= viene interpretato come un confronto. Pertanto, questo confronta B su 0 e quindi assegna il risultato di quel confronto ad A (seguendo la convenzione di tipo C che "falso" risulta in 0 e "vero" in 1).

Quindi, se B era 0, allora A diventa 1. Altrimenti, A diventa 0. In altre parole, invece di assegnare lo stesso valore ad A e B, questo in realtà garantisce che A non possa avere lo stesso valore di B.

In conclusione: anche se lo stile C / C ++ / PHP inizialmente sembra un dolore, l'alternativa è molto peggio 1 .

1 Beh, tecnicamente, c'è un'altra alternativa: lo stile Pascal, dove =sempre il confronto e l'assegnazione richiedono sempre :=. Dopo averlo usato per un po ', è abbastanza ovvio (almeno per me) che il compito è abbastanza più comune del confronto che se hai bisogno di "cose" extra per chiarire le due cose, dovresti sicuramente mantenere i compiti puliti e semplici e richiede il "grunge" extra sui confronti, non viceversa.


1
Proporrei persino di usare ==per l'uguaglianza e :=per il compito. In questo modo hai più da scrivere, ma evitare la solitudine =aiuta a evitare i bug.
maaartinus,

@maartinus: almeno per me, sembra la peggior possibilità assoluta, ma tale è la vita ...
Jerry Coffin,

3

Perl

  1. Vorrei che Perl mi lasciasse scrivere if($x < 10) do_something();. Al momento, devi scriverlo come uno do_something() if($x < 10);o l'altro if($x < 10) { do_something(); }.

9
do_something() if ($x < 10);non è poi così male.
zneak,

Non lo è, e in molti casi è molto più pulito if(..) ...dell'avvio, in quanto è possibile allineare tutte le espressioni sulla destra. Ma ci sono momenti che voglio davvero dire if($x < 10) do_something();, ed è un peccato che Perl non me lo permetta.
Gaurav,

7
È sfortunato finché non scrivi if ($x<10) do_something(); and_call_me(); e poi ti chiedi perché non ricevi mai una chiamata. Vorrei che C e la famiglia richiedessero le parentesi graffe, per evitare questo tipo di errore.
AShelly,

2
@AShelly: o perché ricevi sempre una chiamata, in realtà.
zneak,

1
@zneak Tranne nessun elses. (Vorrei che abbia EXPR1 if COND else EXPR2come Python)
Ming-Tang,

3

reinterpret_cast<unsigned long>in c ++. Questa operazione è utile nel trattare con API straniere e garantire precisione numerica, perché dovrebbe essere un tale dolore da digitare e così brutto da guardare?


17
È brutto ricordarti che dovresti cercare di scrivere codice che non lo richieda. :)
greyfade,

Per me questo è un buon tipo di argomento teorico dell'informatica, ma nella mia esperienza, è troppo utile per evitare (Tuttavia, gran parte della mia esperienza è semplicemente vecchia C, quindi probabilmente ho un pregiudizio).
AShelly,

5
Non è proprio un argomento CS teorico: usare a reinterpret_castin C ++ è un odore di codice molto forte. Il 99% delle volte, quando stai per usarlo, è probabile che non dovresti farlo - probabilmente hai fatto qualcosa di sbagliato. L'altro 1% delle volte, l'interfaccia con C. reinterpret_castinterrompe il sistema dei tipi per far funzionare qualcosa quando altrimenti non può. Di solito è una brutta cosa.
Greyfade,

3

Il costrutto for ... in in JavaScript e il costrutto foreach in PHP quando si esegue il loop su array. Entrambi facilitano la scrittura di bug rispetto al codice corretto.


3
Wow, questa è una cazzata. "Del codice corretto". Va via.
Jonathan Sterling,

Se devo scrivere un codice aggiuntivo per usarli in modo sicuro, sono più facili da usare nel mio libro. For ... in richiede controlli extra per assicurarsi che non si stia ripetendo gli oggetti dal prototipo e foreach richiede in seguito di ripulire i riferimenti o rischiare di sovrascrivere l'ultimo valore nell'array.
Joeri Sebrechts,

la foreach con riferimenti mutevoli (e operatore) è un famoso bug ...
umlcat

1
Sono confuso, pensavo fosse risaputo che il costrutto "for..in" in javascript è rotto ... perché è offensivo?
Leopoli

2

Puntatori di matrici o matrici di puntatori in C / C ++. Sono ancora confuso su questi.


3
Leggi il tipo al contrario. int[]*è un puntatore a un array di numeri interi ed int*[]è un array di puntatori a numeri interi. Funziona bene con consts troppo: int* constè un puntatore costante a numeri interi, mentre const int*e int const*sono puntatori a interi costanti (o costanti intere).
zneak,

@zneak: "Da destra a sinistra" non funziona, vedi la menzionata regola "spirale in senso orario" / " rovescio " .

Oppure usa solo typedef e non c'è confusione.
Billy ONeal,

Nel C ++ moderno c'è pochissima necessità di puntatori e matrici.
fredoverflow,

4
@tchrist: Non vero. int (*p)[10];dichiara pdi essere un puntatore a un array di 10 ints. Se sizeof (int) == 4, allora p++avanzerà pdi 40.
j_random_hacker


1

Javascript / Java ecc., Uguale a confronto, ad es. Se (a == 1)

Quante volte scrivo if (a = 1)?

Da umano l'ho letto perfettamente. Ma l'interprete / compilatore maledetto dice "Ehi, assegnerò 1 a a, quindi verificherò se a è uguale a 1 e ci crederesti che sì!

Mi fa salire il muro.

se (a == 1) è molto meno leggibile e l'interprete / compilatore dovrebbe sapere comunque cosa intendo; molte altre lingue minori (VB) hanno funzionato con successo per centinaia di anni.


Cosa if (a = true)dovrebbe significare?
Tom Hawtin - tackline

2
L'assegnazione non dovrebbe restituire un valore. A volte è utile, ma nella maggior parte dei casi è solo un dolore al collo.
configuratore

in Javascript JSLint lo prenderà per te.
Zaccaria K,

Il problema è che l'assegnazione in condizioni può essere utile. Trovo <tt> while (element = list-> next ()) </tt> abbastanza leggibile. Quindi non sono sicuro che vorrei che fosse rimosso.
Inca,

3
@ Tom: Significa che non capisci i booleani. Se intendevi if (a == true), basta scrivere if (a). Se intendevi a = true, allora l' ifistruzione è ridondante.
dan04,


0

structPointer->memberin C / C ++. Può essere utile per leggere il codice di qualcun altro, ma non mi piace. Due personaggi invece di uno ... che spreco di spazio!


2
Sfortunatamente, deve essere distinto da ., che si applica ai membri di un oggetto non puntatore. La sintassi ambigua è cattiva, mmmkay?
Greyfade,

2
@greyfade: Sì! Perché il compilatore non può usare le sue regole di sistema di tipo per dire quando stai usando un tipo pointer-to-struct e applicare implicitamente la dereference. No, è un discorso folle! (Eppure può ancora in qualche modo darti un messaggio di errore quando lo sbagli.) Non c'è nulla di ambiguo nella sintassi. È solo che C è un casino, come al solito. Delphi fa delle dereferenze implicite bene, se stai effettivamente lavorando in angoli bui che richiedono puntatori-record, quindi può sicuramente essere fatto senza confondere un parser ...
Mason Wheeler,

5
@Mason: Che dire di casi come shared_ptr, dove ->accede al tipo contenuto e .accede alle proprietà dello shared_ptrstesso? Mi dispiace, ma non sono completamente d'accordo qui.
Billy ONeal,

2
potrebbe essere peggio. Potrebbe essere PHP, dove devi usare ->per accedere ai membri di qualsiasi cosa .
Carson Myers il

1
@maaartinus: Qualsiasi codice che si basa fortemente su un ordine non ovvio di operazioni non è il codice che scriverò.
Billy ONeal,

0

Il codice multilinea Scala tra parentesi

Per esempio:

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

Ciò che effettivamente ottieni da esso è eccezionale. Genera il costruttore, i getter e i setter per te. Ma è sicuramente brutto e rompe tutti i miei modelli mentali su come indentare il codice e sostanzialmente mi fa sentire come se fossi in una sorta di bizzarro sandwich con Java da un lato e Lisp dall'altro. (Oh, aspetta ... questo è piuttosto il punto della Scala.)


Sono confuso: intendi la parte tra parentesi ( val bare così via) o la parte tra parentesi graffe (la parte seguente extends Model)? (Non ci sono parentesi in quel codice)
Billy ONeal

3
La parte tra parentesi. Sono inglese. Ci riferiamo a quelli come parentesi, dannazione, perché in quella situazione non stanno svolgendo un ruolo tra parentesi.
Tom Morris,

2
Non sembra poi così male se indentato in questo modo: pastebin.com/h9qC8XGg
missingfaktor

Trovo più leggibile scrivere queste liste di parametri del costruttore in orizzontale, specialmente quando ho solo pochi parametri.
MJP,

A me sembra un metodo. Come Simula. Buona vecchia scuola.
Tom Hawtin - affronta il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.