Jakiego elementu składniowego nienawidzisz najbardziej w języku programowania, którego często używasz? [Zamknięte]
27
Bez względu na to, jak bardzo kochasz język programowania, zawsze jest w nim kilka szczegółów, które nie są tak ładne, jak mogłyby być.
W tym pytaniu chciałbym szczególnie skupić się na elementach składniowych. W języku programowania, którego często używasz (być może twoim ulubionym języku programowania, a może tym, którego zmuszasz się używać w pracy), który element składni uważasz za najbardziej nieczytelny, niejasny, niewygodny lub nieprzyjemny?
@Nathan Taylor, nie dla tego pytania, ale dla innego pytania .
finnw
Czy to pytanie zostało zmodyfikowane? Ponieważ kiedy odpowiedziałem, nie koncentrowałem się na „elementach składniowych” ... Będę musiał teraz zmodyfikować swoją odpowiedź.
Talvi Watia,
@Talvi: Nie, od samego początku chodziło o składnię.
Timwi
@Timwi dziwne, to musi być przypadek „odpowiedzi na pytanie, które uważało, że było inne”.
Talvi Watia,
Jeśli możesz głosować i uważasz, że jest to przydatne pytanie lub poniżej znajdziesz przydatne odpowiedzi, zagłosuj. Witryny StackExchange potrzebują głosów, aby zbudować dobrą społeczność. Możesz dać 30 głosów dziennie, nie marnuj ich. Szczególnie użytkownicy o wysokiej reputacji i niskiej liczbie
Maniero
Odpowiedzi:
39
Wstawianie średnika w JavaScript.
Tak naprawdę nie gryzło mnie to często, ale to tak fenomenalnie zły pomysł, że kręci mi się w głowie.
Oto zasady (z ECMA-262 sekcja 7.9)
Gdy program zawiera token, który nie jest dozwolony przez gramatykę formalną, wstawiany jest średnik, jeśli (a) nastąpiło przerwanie linii lub (b) nieoczekiwany token był klamrą zamykającą.
Po osiągnięciu końca pliku, jeśli program nie może zostać inaczej przeanalizowany, wstawiany jest średnik.
Kiedy napotkamy „ograniczoną produkcję” i zawiera on terminator linii w miejscu, w którym gramatyka zawiera adnotację „[tutaj nie ma LineTerminatora]”, wstawiany jest średnik.
JavaScript: najbardziej niezrozumiany język programowania na świecie ~ Douglas
Crockford
Tak, wielu spodziewa się, że JavaScript będzie „językiem swobodnym”, ale tak nie jest.
Andreas Rejbrand,
13
Ma to sens, gdy zorientujesz się, że JavaScript został zaprojektowany do tworzenia HTML, który ma długą historię interpretacji tego, co twój kod „naprawdę znaczy”, gdy nie jest poprawny pod względem składniowym. (Zobacz kiedyś zasadę solidności - największa katastrofa w historii komputerów.)
Mason Wheeler,
7
Tego rodzaju błędy są dla mnie zapachem kodu, że programista jest niechlujny i nigdy nie działał z większością formalnych „ścisłych” języków, które normalnie powodowałyby błąd składniowy w przypadku pominięcia średnika.
Talvi Watia,
7
Wohoo, wreszcie ktoś jeszcze, kto uważa, że Zasada Wytrzymałości to katastrofa, która sprawiła, że HTML stał się kompletnym bałaganem.
Roman Starkov,
39
Składnia Java-bean z powodu braku właściwości 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 !!!
Mam z tym problemy
Za dużo kodu - Mieć udokumentowane pole, udokumentowaną metodę pobierającą i udokumentowaną metodę ustalającą. Ten niezwykle podstawowy przykład zawiera 20 wierszy kodu dla pojedynczej właściwości
Zaśmiecanie listy metoda - „Pozwól mi znaleźć tę metodę, ręcznie na: getX, getY, getZ, getAnotherAnnoyingField, getWhyIHateJavaBeans, getThisIsVerbose, getGAH... ah tam to jest hashCode.
Wiele obszarów dokumentacji prowadzi do słabej, nieaktualnej lub brakującej dokumentacji - denerwujące, gdy próbujesz zrozumieć, co robi kod
Tak irytujące osoby trzecie musiały opracować wtyczkę, aby zrobić to łatwo - między innymi Spoon , Shark .
Raz jeszcze, gdy kod jest tak szczegółowy, że potrzebuje narzędzi do automatycznego generowania, coś jest nie tak. Jestem facetem NetBeans, ale ma także możliwość automatycznego generowania getterów i setterów. Ale Javadoc wypada z synchronizacji, wciąż jest gadatliwy, wciąż zaśmieca javadoc itp.
TheLQ
11
Jeśli potrzebujesz getterów do wszystkiego, coś jest nie tak z kodem klienta .
finnw
7
Posiadanie getterów i seterów przerywa enkapsulację. Pole może równie dobrze być public. Członkowie powinni być prywatni i powinni być rozsądnie manipulowani przez klasę za pomocą logiki wyższego poziomu, a nie za pomocą programów pobierających i ustawiających z kodu klienta.
greyfade
6
@greyfade: Jeśli jest publiczny, nie możesz łatwo zmienić działania kodu ustawień (musisz zmienić cały kod ustawiający pole z zewnątrz).
Bart van Heukelom,
3
@SHiNKiROU: Java wygląda czysto? Nigdy wcześniej tego nie słyszałem! Główną wadą Javy jest fakt, że z pozoru prosta rzecz wymaga dziesiątek linii kodu, które muszę mentalnie zignorować.
konfigurator
33
Czułość białych znaków.
Python denerwuje mnie pod tym względem. To znaczy, ja wciąć właściwie w każdym razie, ale robaki mi, że powinienem mieć do. Irytują mnie włączenie prezentacji do składni.
Oto przykład, dlaczego uważam to za bardzo niewygodne:
switch (someVariable)
{
case 1:
int i = something();
doSomething(i);
break;
case 2:
int i = somethingElse();
doSomethingElse(i);
break;
}
Nie kompiluje się, ponieważ zmienna ijest ponownie zadeklarowana w tym samym zakresie. To wydaje się drobnym szczegółem, ale bardzo często mnie gryzie. Mogę dodawać nawiasy klamrowe, aby je złagodzić, ale byłoby miło, gdyby nawiasy klamrowe były obowiązkową częścią składni i nie było zbędnego dodatkowego poziomu wcięcia. Naprawdę nie lubię też pisać dodatków break. Byłoby to o wiele ładniejsze:
switch (someVariable)
case 1
{
int i = something();
doSomething(i);
}
case 2
{
int i = somethingElse();
doSomethingElse(i);
}
default
{
...
}
To sprawia, że wygląda bardziej jak łańcuch if/ else, co jest dobre, ponieważ jest również semantycznie podobne. Przynajmniej w języku C # nie byłoby to jednak to samo, ponieważ w switchinstrukcji kolejność etykiet wielkości liter nie ma znaczenia, ale w if/ elsema to znaczenie.
Niestety, twoja ulepszona składnia eliminuje to, co jest prawdopodobnie największą funkcją przełącznika w większości z tych języków: Fall-through. „Urządzenie Duffa” w C jest doskonałym przykładem wartości tej szczególnej „błędnej funkcji”. W językach podobnych do C często stosuje się awarie w tłumaczach i podobnych programach.
greyfade
7
Nie, to nic nie da. Wymaga tylko, aby było to bardziej wyraźne (przy użyciu gotopodobnego lub podobnego), jak ma to już miejsce w języku C #.
Timwi
8
@greyfade: Każdy kod używający urządzenia duffa w C musi umrzeć straszną śmiercią. Kompilatory podejmują lepsze decyzje dotyczące tego rodzaju rzeczy niż ty.
Billy ONeal
4
@greyfade: Delphi dostaje po wielokrotnych wartości emisyjnej, po prostu pozwalając wielu indeksów w przypadku: case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;.
Frank Shearar
3
@jkerian: Teraz wyobraź sobie, że breakbył domyślny i trzeba było określić tylko upadek. Nie musisz już tego komentować! :)
Timwi
27
Deklaracje tablic w VB.NET
Zawsze udaje mi się zapomnieć, że inicjując stałe tablice w VB.NET, określasz górną granicę tablicy, a nie liczbę elementów, jak w C / C ++, PHP czy Java. Poza VB6 (tam nie pojedziemy ...) nie mogę wymyślić innego języka, który robi to w ten sposób:
Dim myArray(20) as Integer '# Creates an array with 21 elements,
'# indexed from 0 to 20
+1 za używanie VB6 jako najczęściej używanego języka.
Walter
9
Używam tego codziennie..sob.
systempuntoout
Czy Pascal nie ma podobnej składni? Zawsze myślałem, że to okropne.
greyfade
1
Istnieje szczególny przypadek: jeśli ty Dim Hurp As New Collection, jeśli uzyskasz dostęp, Hurpgdy odnosi się do Nothingniego, zostanie on magicznie zainicjowany przed dostępem. Jeśli wyraźnie go ustawisz Nothingi dotkniesz go ponownie, zostanie wskrzeszony ... sapie!
Jeffrey Hantin,
1
+ 1 milion za Derp. Derp de derp de tiddly tum de derp.
MVCylon
24
Komentowanie w CSS
//nie komentuje wierszy kodu, jak ma to miejsce w wielu innych językach, takich jak PHP i JavaScript. Chociaż /* this is commented out */działa, wolę używać //.
Jest to uciążliwe, ponieważ w połowie przypadków zapominam, że edytuję CSS, a następnie muszę wrócić i naprawić błąd.
W dzisiejszych czasach można by pomyśleć, że surowy CSS będzie uważany za kod obiektowy.
Tom Hawtin - tackline
// działa dobrze, aby skomentować CSS. Ciągle to robię. Wszystko, co naprawdę robię, to pisanie śmieci. ale wydaje się, że działa, pomijając nie dającą się oddzielić linię.
MVCylon
1
@MVCylon Jeśli użyjesz // do skomentowania linii, wszystko po tej kolejnej linii również zostanie pominięte. {w ramach tego konkretnego stylu} Innymi słowy, NIE DZIAŁA, ponieważ te linie nie powinny być pomijane.
Talvi Watia,
20
PHP - spójne porządkowanie argumentów
PHP ma wiele przydatnych funkcji do wykonywania praktycznie każdej operacji, o której można pomyśleć na tablicy lub łańcuchu. Wiele z tych operacji wymaga użycia zarówno a, jak $needlei a $haystack, ale różne funkcje przyjmują je w różnych kolejności. Która funkcja wymaga, które argumenty są jednym z tych faktów, których mój mózg nie chce przyswoić, bez względu na to, jak często je spotykam!
// 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])
Co zabawne, PHP wydaje się być wewnętrznie spójne z tymi porządkami, ponieważ wszystkie funkcje łańcuchowe wydają się używać, $haystack, $needlepodczas gdy funkcje tablicowe są na odwrót, ale może to trochę przyzwyczaić się dla kogoś nowego w PHP. W ExpressionEngine jest dobry post, który mówi o tym dziwactwie bardziej szczegółowo, a także dyskusja na liście błędów PHP , która zawiera bardzo krótką odpowiedź od zespołu PHP!
Łatwiej jest zapamiętać kolejność $needle, $haystackponieważ przypomina sposób na znalezienie igły w stogu siana .
kiamlaluno
3
Protip: w funkcjach tablicowych igła jest na pierwszym miejscu. w funkcjach łańcuchowych stóg siana jest na pierwszym miejscu.
GSto
17
Kocham to imię strstr. Tak pięknie bez znaczenia.
konfigurator
5
Wystarczy przeczytać link do wpisu w programie do śledzenia błędów PHP. Poważnie, wtf? oO Spójność Imho jest prawidłowym problemem dla dowolnego interfejsu API, a samo odpowiadanie „użyj przyzwoitego IDE wtedy” nie jest prawidłową odpowiedzią. Twórcy mogli przynajmniej powiedzieć, że jest mniej zapalny.
Baelnorn
2
Szczerze mówiąc, doprowadza mnie to do szału, że wcale nie powinna to być funkcja! Powinna to być po prostu metoda: $ haystack-> find ($ igła). Skończona sprawa.
W metodzie klasowej zwykle nazywa się ją cls, a używanie self jest sprzeczne z konwencją.
To ma sens, jeśli się nad tym zastanowić. Jest to to samo, co deklarowanie metody prywatnej w innych językach, parametr własny jest po prostu jawny w pythonie, gdzie jest niejawny w innych językach. Jeśli chcesz, aby było to niejawne, dodaj dekorator @classmethod przed deklaracją metody. Zobacz docs.python.org/library/functions.html#classmethod . Zapoznanie się ze szczegółami tego, jak to działa, pozwoli ci uzyskać wgląd w sposób pośredni w innych językach.
@Evan Plaice: „parametr własny jest po prostu jawny w pythonie, gdzie jest niejawny w innych językach” To tylko jedna część historii. Druga część to pisanie co tydzień python. Razem jest to okropne, zapominanie selfzdarza się łatwo i kosztuje czas.
maaartinus,
@maaartinus Następnie dodaj dekorator metody klasy do metod instancji. Nie ma nic wspólnego z „słabo wpisanym”. Po prostu uwidacznia związek między metodami statycznymi / funkcjami (brak parametru „ja”) a metodami instancji (obejmuje „jaźń”). Metoda instancji nie jest świadoma swojej klasy nadrzędnej, chyba że podasz jej referencję. W innych językach wyróżniająca mnie cecha jest po prostu ukryta za cukrem syntaktycznym. Gdybym miał wybór, żeby to zrobić od początku, najpierw zacząłbym uczyć się OOP w Pythonie.
Evan Plaice,
18
Jawa
Kropka. Kropka. Koniec opowieści.
Gdzie zacząć? Och, wiem od czego zacząć: niesamowicie skomplikowana i brzydka, głupia i z natury zepsuta Java . Czy muszę powiedzieć więcej? :( Ok dobrze, a następnie: wpisz kasowanie .
Potem jest niedeterministyczne zarządzanie zasobami. Kewl footcher!
Co dalej? O tak: Głupie wyrażenia Javy to moja najbardziej irytująca, kipiąca wołowina. Nie mogę zliczyć, ile razy mnie nie było, ponieważ nie miałem wystarczającej liczby ukośników. Jest to nawet gorsze niż brak dostępu do jakichkolwiek właściwości Unicode z tego tysiąclecia - co jest całkowitym bykiem. Dziesięć cholernych lat nieaktualnych !!! Kompletnie bezużyteczny. Wyrzuć to.
Następnie jest błąd polegający na tym, że skróty klas postaci nie działają na nie-ASCII. Co za królewski ból! I nawet nie rozważaj używania \p{javaWhiteSpace}; nie robi to dobrze z kilkoma bardzo powszechnymi punktami kodowymi spacjami w Unicode.
Czy wiesz, że jest \p{javaJavaIdentifierStart}nieruchomość? Co oni sobie myślą? Tak się cieszę, że mają tak inteligentnych podglądaczy na twardo.
Czy kiedykolwiek próbowałeś użyć flagi CANON_EQ? Czy wiesz, że to naprawdę działa, a czego nie robi? Co powiesz na tak zwaną „przypadek Unicode”? Kilka normalnych obudów po prostu w ogóle nie działa.
Potem utrudniają pisanie możliwych do utrzymania wyrażeń regularnych. Java wciąż nie wymyślił, jak pisać ciągi wielowierszowe, więc w końcu piszesz takie szalone rzeczy:
Co to są te wszystkie nowe linie? Och, tylko głupota Java. Używali komentarzy Perla, a nie komentarzy Javy ( idioci! ), Które przechodzą do końca linii. Więc jeśli nie umieścisz ich \ntam, odetniesz resztę swojego wzoru. Duh i double duh!
Nie używaj wyrażeń regularnych w Javie: po prostu skończysz z chęcią zniszczenia rzeczy, wszystko jest tak bolesne i zepsute. Nie mogę uwierzyć, że ludzie to znoszą. Niektórzy nie .
Następnie możemy zacząć mówić o idiotycznych nonsensach Javy za pomocą kodowania. Po pierwsze, domyślnym kodowaniem platformy jest zawsze słabe 8-bitowe kodowanie, mimo że znaki Java są Unicode. Jest też sposób, w jaki nie zgłaszają wyjątku dotyczącego błędu kodowania. Gwarantujesz bzdury. A może to:
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.
Co za różnica? Czy wiesz, że tylko jeden z nich zgłosi wyjątek, jeśli wystąpi błąd kodowania? Reszta po prostu kaganiec.
Potem idiotyzm znaków Java nie wystarcza do utrzymania postaci! Co oni do diabła myślą? Dlatego nazywam je charcharami. Musisz napisać taki kod, jeśli spodziewasz się, że działa poprawnie:
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("."); }
}
}
A kto kiedykolwiek myśli, aby to zrobić? Obok nikogo.
Ile tam jest znaków "\uD83D\uDCA9"? Jeden lub dwa? Zależy jak je policzysz. Silnik regex oczywiście zajmuje się znakami logicznymi, więc wzorzec ^.$się powiedzie, a wzorzec ^..$się nie powiedzie. Owo szaleństwo zostało pokazane tutaj:
Ten idiotyzm polega na tym, że nie możesz napisać całkowicie rozsądnego \u1F4A9, ani oczywiście nie otrzymujesz ostrzeżenia, że nie możesz tego zrobić. Po prostu robi to źle.
Głupiutki.
Skoro już o tym \uXXXXmowa, cała notacja jest wrodzona martwa dla mózgu. Preprocesor Java ( tak, słyszałeś mnie ) dotrze do niego, zanim zrobi to Java, więc nie wolno ci pisać całkowicie rozsądnych rzeczy, takich jak "\u0022", ponieważ zanim Java to zobaczy, jego preprocesor zmienił go """, więc przegrywasz. Och, czekaj, nie, jeśli to wyrażenie regularne! Możesz więc dobrze wykorzystać "\\u0022".
Riiiiiiiight!
Czy wiesz, że w Javie nie ma możliwości wykonania isatty(0)połączenia? Nie wolno ci nawet myśleć takich myśli. To nie byłoby dla ciebie dobre.
A potem jest cała obrzydliwość klasy.
Lub fakt, że nie ma sposobu, aby określić kodowanie pliku źródłowego Java w tym samym pliku źródłowym, aby go nie zgubić? Po raz kolejny żądam wiedzieć: CO CHCĘ BYŁO MYŚLENIE‽‽‽
Powstrzymać szaleństwo! Nie mogę uwierzyć, że ludzie znoszą te śmieci. To kompletny żart. Wolałbym być powitaniem Walmarta niż cierpieć z powodu procy i strzały oburzającego szaleństwa na Jawie. Wszystko jest zepsute i nie tylko nie mogą tego naprawić, ale nie naprawią tego.
To przez tych samych winorośli, którzy szczycili się językiem, w którym printf()funkcja była nielegalna . Ojej, to na pewno zadziałało naprawdę, prawda ?!
Zwykłe zdrętwiałe czaszki. Policzkowanie suk jest dla nich zbyt miłe. Gdybym chciał zaprogramować w asemblerze, zrobiłbym to. To nie jest język do ocalenia. Cesarz nie ma ubrania.
Nienawidzimy tego. Nienawidzimy tego na zawsze . Niech umrze umrze umrze !
Haha, dobra, nie dotykam java, ponieważ jest zbyt niepolerowana, jak to opisujesz. Jeśli chodzi o \ uD83D ... cóż, lepiej jest powiedzieć, że wolisz, aby łańcuchy nie były UTF-16, a UTF-32. Jeśli zaakceptujesz UTF-16-ness, to wyrażenie regularne postąpi właściwie; to połączenie .length, które się pieprzy.
Roman Starkov
4
-1. Z wyjątkiem komentarzy wyrażeń regularnych i znaków ucieczki Unicode, żadna z wymienionych rzeczy nie jest elementem składni.
Jörg W Mittag
3
@ Jörg, chcesz składnię? Ok dobrze: Java pozwala wstawiać znaki kontrolne, w tym ESC i NUL, w identyfikatorach. WTH oni myśleli ???
tchrist
4
@tchrist: Wow! Jeśli kiedykolwiek napiszę ponownie program Java, wszystkie moje zmienne będą miały nazwy składające się ze zmiennej liczby znaków backspace ( ^H) :)
j_random_hacker
1
@ tchrist, czujesz się teraz lepiej?
16
Składnia deklaracji wskaźnika funkcji w C i C ++:
(int)(*f)(int, int);
Deklaruje on wskaźnik funkcji o nazwie, fktórego pointee może zająć dwa intsi zwrócić an int.
Wolałbym taką składnię:
f: (int, int) => int
Powiedzmy, że chcesz zadeklarować wskaźnik funkcji g, której wskazywany może przybrać dwie ints oraz funkcję od inti intdo int, i zwrócić int.
W notacji C lub C ++ zadeklarujesz ją jako:
(int)(*g)(int, int, int(int, int));
Dzięki powyższej notacji to samo można zadeklarować jako:
g: (int, int, (int, int) => int) => int
Później jest o wiele bardziej intuicyjny IMO.
Poza tym: język programowania o nazwie OOC naprawia tę składnię (i różne inne problemy składniowe w C i C ++). Sprawdź jego stronę główną tutaj .
Zgadzam się, niektóre „zwykłe C” / „C ++” nie obsługują go lub obsługują inną składnię. Specjalna składnia pomaga wskazać, kiedy obsługiwana jest funkcja języka programowania. Właśnie dlatego C # dodał składnię „delegować”.
umlcat
Delegaci są nie tylko składniowym cukrem, ponieważ przechowują również obiekt (w przeciwieństwie do wskaźników funkcji
„public static final int x = 4;” w porównaniu do „x = 4” w Haskell.
Jared Updike,
24
To nie jest gadatliwość. Spróbuj napisać a+(b*c)/d*e+f/g^20używając BigIntegerw Javie. Dlaczego ten język nie pozwala na przeciążanie operatora?
MAK
4
@Michael: programiści, którzy muszą być chronieni przed sobą tymi kosztami, mogą najlepiej chronić siebie (i zmniejszyć ból dla wszystkich innych), nie programując wcale: D.
MAK
12
\ my \ wouldnt \ fix \ our \ parser namespace w PHP
Składnia jest nie tylko brzydka, ale prowadzi do zamieszania, gdy nowi programiści muszą myśleć o przestrzeniach nazw w łańcuchach. (PHP interpoluje ukośniki odwrotne w ciągach podwójnie cytowanych jako sekwencje specjalne. Próba reprezentowania przestrzeni nazw jak \you\should\never\do\thatw ciągach podwójnych zamiast ciągów pojedynczych doprowadzi do znaków nowej linii, tabulatorów i katastrofy.)
Tak, ktoś wymyślił lepszy sposób ::, ale PHP nalega, aby każdy operator był inny. Jestem jednak ciekawy, na czym polega problem niewłaściwego użytkowania.
Alan Pearce
Zgodzić się. PHP wymaga przestrzeni nazw, ale ta składnia
psuje
9
Nienawidzę faktu, że nawiasy klamrowe mogą być opcjonalne po instrukcji if / while / for.
Hmm .. to zależy. W przypadku „Abort Ifs”, które jedynie sprawdzają warunek i zwracają kod błędu (lub zgłaszają wyjątek), wolałbym nie widzieć nawiasów klamrowych.
Billy ONeal,
4
Zgodziłbym się, gdybyście ograniczyli się do ekstremalnych spraw wielopoziomowych, ale wasze oświadczenie jest zbyt ogólne. Istnieje ogromna użyteczność w postaci krótkich formularzy dla prostych, pojedynczych instrukcji if i pętli.
Timwi
2
Moja zasada: tylko jeśli instrukcja wymaga wielu podstacji lub jeśli zawiera taką instrukcję, powinna być owinięta nawiasami klamrowymi. Dlatego for (...) while (...) if (...) { x(); y(); }lepiej jest przepisać, jak for (...) { while (...) { if (...) { x(); y(); } } }oczywiście przy odpowiednim wcięciu.
Jon Purdy,
6
Raczej przeciwnie - gardzę ludźmi, którzy upierają się przy zakładaniu aparatów ortodontycznych, gdy są zupełnie niepotrzebni. Naucz się programować.
Jerry Coffin
3
Naprawdę podoba mi się nawiasy nawet w pojedynczych instrukcjach if. To sprawia, że lepiej śledzę przebieg programu.
Ricardo Santos,
9
VBScript nie ma operatorów logicznych
W przeciwieństwie do prawie każdego rozsądnego języka, VBScript używa operatorów bitowych zamiast operatorów logicznych. Co to oznacza w praktyce? Cóż, jak zauważa Eric Lippert :
If Blah = True Then Print "True!" Else Print "False!"
i
If Blah Then Print "True!" Else Print "False!"
NIE są takie same w VBScript!
Co gorsza, choć oznacza to, że nie ma oceny zwarcie w VBScript dlatego poniższe oświadczenie będzie rozbić swój program, jeśli Blahjest w stanieNothing
If (Not Blah Is Nothing) And (Blah.Frob = 123) Then
...
Zgadza się, VBScript oceni obie części porównania AND, nawet jeśli pierwsza jest fałszywa! Po prostu pozwól temu zatonąć ...
Aż do dnia, w którym polujesz na błąd wewnątrz If x Then ... If Not x Then ... End If ... End Ifi zorientujesz się, że x wynosi 2, tak naprawdę nie programowałeś w VB / VBScript.
konfigurator
7
EDYCJA: Po dyskusji w komentarzach postanowiłem zaktualizować tę odpowiedź, aby lepiej się wyjaśnić.
Naprawdę nie znoszę wyglądu wskaźników funkcji w C. Zwykle każda deklaracja zmiennej wygląda jak krotka: type varname;
Z drugiej strony deklaracje wskaźnika funkcji wyglądają jak deklaracja funkcji z * przed nazwą funkcji. Mogę zaakceptować to jako opis typu wskaźnika, ale w C deklaruje zarówno typ, jak i nazwę zmiennej tego typu. Wydaje mi się to niespójne, ponieważ deklaracje typów różnią się od deklaracji zmiennych. struct myStruct{int X; int Y;}definiuje tylko typ, nie definiuje zmiennej o nazwie myStruct. Podobnie nie widzę powodu, aby deklaracje typów i deklaracje zmiennych były grupowane w jedną instrukcję atomową we wskaźnikach funkcji, ani też nie doceniam odchylenia od type varname;struktury.
Ktoś zauważył, że jest to zgodne z pewną regułą spiralną i może tak być, ale cechą dobrej składni jest to, że jest ona oczywista, a jej wewnętrzna logika jest oczywista. Reguła spiralna nie jest w żaden sposób oczywista.
Jest spójny z resztą języka, więc może twoja podstawowa zasada dotyczy składni deklaratorów C w ogóle? Czy wolisz składnię używaną w Go ?
finnw
Spójny w jaki sposób? Zwykle idzie: wpisz varname; A kiedy tworzymy nowy typ złożony, taki jak struct, najpierw pojawia się deklaracja, być może z typedef, a następnie tworzymy zmienną tego typu. Kiedy deklarujemy wskaźnik funkcji, jest to int (* foo) (int arg1, int arg2), który jest następnie używany jako typ argumentu przekazywanego do funkcji: void newFoo (int (* foo) (int arg1, int art2 )) .... i jako zmienna: foo = a_compatible_func; Myślę, że najpierw deklaracja funkcji, a następnie deklaracja var byłaby bardziej spójna, na przykład: typedef int (* foo) (int, int) MyFoo; MyFoo myfoo;
EpsilonVector
Właśnie dlatego masz typedef.
zneak
4
@EpsilonVector: Zgadzam się, że składnia wskaźnika funkcji jest nieprzyjemna, ale jest prosta reguła, która ułatwia czytanie. Reguła spiralna zgodna z
greyfade
1
EpsilonVector: Nie jestem pewien, czego można oczekiwać od deklaracji zmiennej wskaźnikowej innej niż nazwa zmiennej.
6
Średniki w VBScript - lub ich brak
Cały dzień pracuję w językach, które oczekują średników na końcu każdej linii. Dodaj jeden na końcu wiersza w VBScript, a Twój kod nie będzie już działał.
głosowanie za tym, nie dlatego, że szczególnie lubię średniki, ale dlatego, że naprawdę nienawidzę sposobu, w jaki VB zachęca do naprawdę długich linii , czyniąc łamanie linii tak niewygodnym.
Shog9
6
Argumenty wejścia / wyjścia. Jestem za argumentami (dobrze, że jestem), nasze argumenty też są w porządku, ale argument, który musi przekazać te dwa stany, wkurza mnie.
To, co tu celuję, to funkcje, które pobierają dane wejściowe z parametru, a następnie nadpisują je danymi wyjściowymi. Można przekazać obiekt przez odniesienie, aby go zaktualizować. Ale, głównie w przypadku typów pierwotnych, zabranie obiektu, użycie go, a następnie całkowita zmiana, nie jest dla mnie właściwe. Nie powinieneś zmieniać znaczenia argumentu poprzez inout.
W jakim języku masz na myśli? Jeśli C #, to nie zgodziłbym się, że to denerwujące, ponieważ zawsze jest jawne (w przeciwieństwie do C ++.) Ponadto nie znam żadnego głównego języka, w którym jesteś zmuszony zadeklarować argumenty jako in / out.
finnw
@finnw Nigdy nie widziałem to język, w którym miał do powiedzenia inna inargumentach albo, ja mówię tylko o nich. Ponadto, moim zdaniem, nic nie może usprawiedliwić argumentu wejścia / wyjścia, a ich wyraźne nie łagodzi bólu. Nie powinno być żadnego powodu, aby inicjalizować zmienną lokalną wartością pomocną dla funkcji i mieć tę samą zmienną, która nagle zawiera wszystko, co funkcja postanowiła tam umieścić. Te dwa powinny być różne. Zawsze.
zneak
Przepraszam, nie byłem tam bardzo jasny. Chciałem powiedzieć „nie znam żadnego języka, w którym wszystkie argumenty są domyślnie włączone + wyłączone”, tzn. Nie jesteś zmuszony do korzystania z tej funkcji, ale istnieją uzasadnione przypadki użycia (np. Aktualizacja miejsca, w structktórym nowa wartość zależy od wartości innego pola tego samego struct.)
finnw
@finnw Obiekty przekazywane przez referencję (jak instancje classobiektów w C #) modyfikowane przez funkcję są dla mnie w porządku. Pomijając, że nie lubię stałe przypisać struktury, mijając structprzy refsłowo kluczowe aby zaktualizować to jest w porządku, zbyt. Naprawdę nienawidzę, gdy dane wejściowe są nadpisywane danymi wyjściowymi. Najlepszym przykładem, jaki mogę wymyślić, jest acceptfunkcja gniazda Berkeley : potrzebuje socklen_t*argumentu, który na wejściu musi zawierać rozmiar struct sockaddr*przekazanego; a na wyjściu będzie zawierać liczbę bajtów, które zostały do niego zapisane. To powinno być kryminalne.
zneak
Zgadzam się, że jest zły (IIRC niektóre funkcje I / O Win32 robią to samo), ale jest to niewłaściwe użycie funkcji (wywołanie funkcji zmienia znaczenie przekazywanej zmiennej, a nie tylko jej wartość) i nie oznacza funkcji samo w sobie jest złe.
finnw
6
Deklaracje tablicowe w C i C ++.
Zazwyczaj deklaracja zmiennej ma format type variable_name. Możesz łatwo odczytać te deklaracje w sposób od lewej do prawej. Ale int foo[size]na początku wygląda na to, że deklaruje się foojako liczbę całkowitą, a potem czytasz dalej i widzisz tego typu „tablica liczb całkowitych”. int[size] fooczyta znacznie lepiej.
I ja też cierpię, kiedy programiści zadeklarować wskaźniki takie jak to z podobnego powodu: int *foo. Z jakiegoś powodu nie zorientowałem się, że jest to typowy sposób, w jaki jest napisany.
Re deklaracje wskaźnika: są tak napisane, ponieważ „ ” wiąże się z nazwą zmiennej, a nie z typem. Tak int* a, b;* nie deklaruje ai bjako wskazówki; tylko ajest. Dlatego lepiej jest napisać to jako int *a, b;(lub nawet lepiej napisać je jako dwie deklaracje).
Steve Melnikoff,
Słuszna uwaga. Szkoda, *że nie wiąże się z typem.
Jakub
2
A to nie wspominając o wskaźnikach funkcji ... void(int) *f;? Nie:void (*f)(int);
Uwaga do siebie - wymyśl imię
We współczesnym C ++ bardzo niewiele jest potrzebnych wskaźników i tablic.
fredoverflow
2
@ Steve Melnikoff: Chociaż dałem +1 tej odpowiedzi, myślę, int* a, b;że wspomniany przez ciebie problem jest znacznie bardziej skandaliczny.
j_random_hacker
5
Nadmiarowa parametryzacja w Javie:
HashMap<String,HashMap<String,String>> foo = new HashMap<String, HashMap<String, String>>();
Co drugi typ parametryzacji kompilator myślećfoo może mieć?
Mam nadzieję, że zdajesz sobie sprawę z wnioskowania o typie Javy (ograniczona)? HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
finnw
1
Java 7:HashMap<String,HashMap<String,String>> foo = new HashMap<>();
Bart van Heukelom
5
Cóż, może mieć dowolny typ, typy i tak są kasowane ...
konfigurator
Masz na myśli brak wnioskowania o typie?
missingfaktor
What other type parameterization does the compiler think foo could have?- Bez względu na powód, dla którego to jest typ surowy - tak jakby ktoś przy zdrowych zmysłach miksowałby typy surowe i sparametryzowane.
maaartinus
5
Ponieważ ludzie już narzekali na =vs. ==, pozwól mi wskazać znacznie gorszą alternatywę. PL / Miałem jedno :=i drugie =, ale gdy coś było „oczywiście” zadaniem, pozwoliłoby ci to uniknąć korzystania =z niego. Użycie :=pozwala zmusić coś do przypisania w sytuacji, w której kompilator inaczej interpretowałby to jako porównanie.
Niestety kompilator nie zawsze decydował o tym, czego można się spodziewać. Rozważ tylko jeden oczywisty przykład:
A = B = 0;
Teraz, dla większości osób znających większość „zwykłych” języków, znaczenie tego jest dość oczywiste - przypisz 0 zarówno A, jak i B. PL / I jest tylko trochę… inny. Z powodów znanych tylko (szalonym) projektantom języka pierwszy =jest interpretowany jako zadanie, ale drugi =jest interpretowany jako porównanie. Dlatego porównuje B do 0, a następnie przypisuje wynik tego porównania do A (zgodnie z konwencją typu C, że „fałsz” powoduje 0 i „prawda” w 1).
Tak więc, jeśli B było 0, to A staje się 1. W przeciwnym razie A staje się 0. Innymi słowy, zamiast przypisywać tę samą wartość A i B, to faktycznie gwarantuje, że A nie może mieć takiej samej wartości jak B.
Podsumowując: chociaż styl C / C ++ / PHP początkowo wydaje się być bólem, alternatywa jest znacznie gorsza 1 .
1 Cóż, technicznie rzecz biorąc, istnieje inna alternatywa: styl Pascala, gdzie =zawsze oznacza, że porównanie i przypisanie zawsze wymaga :=. Po pewnym czasie korzystania z tego jest dość oczywiste (przynajmniej dla mnie), że przypisanie jest o wiele bardziej powszechne niż porównanie, że jeśli będziesz potrzebować dodatkowych „rzeczy” w celu ujednolicenia tych dwóch, zdecydowanie powinieneś zachować zadania czyste i proste i wymagają dodatkowego „grunge” przy porównaniach, a nie odwrotnie.
Proponuję nawet użyć ==do równości i :=do zadania. W ten sposób masz więcej do pisania, ale unikanie samotności =pomaga uniknąć błędów.
maaartinus,
@maartinus: przynajmniej dla mnie to brzmi jak absolutnie najgorsza możliwość, ale takie jest życie ...
Jerry Coffin
3
Perl
Chciałbym, żeby Perl pozwolił mi pisać if($x < 10) do_something();. W tej chwili musisz napisać to jako jedno do_something() if($x < 10);lub drugie if($x < 10) { do_something(); }.
Nie jest, a w wielu przypadkach jest znacznie czystszy niż if(..) ...rozruch, ponieważ wszystkie wyrażenia można ustawić po prawej stronie. Ale są chwile, które naprawdę chcę powiedzieć if($x < 10) do_something();, i to niefortunne, że Perl mi na to nie pozwala.
Gaurav,
7
To niefortunne, dopóki nie napiszesz, if ($x<10) do_something(); and_call_me(); a potem nie zastanawiasz się, dlaczego nigdy nie dostajesz telefonu. Chciałbym, żeby C i rodzina potrzebowali nawiasów klamrowych, aby zapobiec tego rodzaju błędom.
AShelly
2
@AShelly: a właściwie dlaczego zawsze otrzymujesz połączenie.
zneak 10.09.10
1
@zneak Z wyjątkiem nie elses. (Chciałbym, żeby było tak EXPR1 if COND else EXPR2jak Python)
Ming-Tang,
3
reinterpret_cast<unsigned long>w c ++. Ta operacja jest przydatna w radzeniu sobie z zagranicznymi interfejsami API i zapewnianiu precyzji liczbowej, dlaczego pisanie i tak brzydki jest taki trud?
Brzydko jest przypominać, że powinieneś starać się pisać kod, który tego nie wymaga. :)
greyfade
Dla mnie jest to dobry teoretyczny argument informatyczny, ale z mojego doświadczenia jest zbyt użyteczny, aby go unikać (jednak większość mojego doświadczenia to zwykłe stare C, więc prawdopodobnie mam stronniczość).
AShelly
5
To nie jest tak naprawdę teoretyczny argument CS: użycie reinterpret_castw C ++ jest bardzo silnym zapachem kodu. W 99% przypadków, kiedy masz zamiar go użyć, są szanse, że nie powinieneś - prawdopodobnie zrobiłeś coś złego. Pozostały 1% czasu łączysz się z C. reinterpret_castłamie system pisma, aby coś działało, gdy inaczej by nie było. To zwykle zła rzecz.
greyfade
3
Konstrukcja for ... w JavaScript i konstrukcja foreach w PHP podczas zapętlania tablic. Oba ułatwiają pisanie błędów niż poprawny kod.
Wow, to takie bzdury. „Niż poprawny kod”. Idź stąd.
Jonathan Sterling
Jeśli muszę napisać dodatkowy kod, aby bezpiecznie z nich korzystać, łatwiej jest je źle wykorzystać w mojej książce. For ... in wymaga dodatkowych kontroli, aby upewnić się, że nie iterujesz obiektów z prototypu, a foreach wymaga późniejszego czyszczenia referencji lub ryzykowania zastąpienia ostatniej wartości w tablicy.
Joeri Sebrechts
foreach ze zmieniającymi się referencjami (i operatorem) to słynny błąd ...
umlcat,
1
Jestem zdezorientowany, myślałem, że powszechnie wiadomo, że konstrukt „for..in” w javascript jest zepsuty ... dlaczego to jest obraźliwe?
lvilnis
2
Wskaźniki tablic lub tablice wskaźników w C / C ++. Nadal jestem tym zdezorientowany.
Przeczytaj typ do tyłu. int[]*jest wskaźnikiem do tablicy liczb całkowitych i int*[]jest tablicą wskaźników do liczb całkowitych. Działa również dobrze z consts: int* constjest stałym wskaźnikiem do liczb całkowitych, natomiast const int*i int const*jest wskaźnikami do stałych liczb całkowitych (lub stałych liczb całkowitych).
JavaScript / Java itp., To porównanie, np. If (a == 1)
Ile razy piszę, jeśli (a = 1)?
Jako człowiek doskonale to rozumiem. Ale cholerny interpreter / kompilator mówi: „hej, przypiszę 1 do a, następnie sprawdź, czy a jest równe 1, i czy uważasz, że tak!
Wbija mnie w ścianę.
if (a == 1) jest znacznie mniej czytelny, a interpreter / kompilator powinien wiedzieć, co mam na myśli; wiele innych mniejszych języków (VB) opracowuje je z powodzeniem od setek lat.
Zadanie po prostu nie powinno zwracać wartości. Czasami jest to przydatne, ale w większości przypadków jest to tylko ból szyi.
konfigurator
w JavaScript JSLint złapie to dla ciebie.
Zachary K
Problem w tym, że przypisanie w warunkach może być przydatne. Uważam, że <tt> while (element = list-> next ()) </tt> jest dość czytelny. Więc nie jestem pewien, czy chciałbym, żeby to zostało usunięte.
Inca
3
@Tom: Oznacza to, że nie rozumiesz wartości logicznych. Jeśli miałeś na myśli if (a == true), po prostu napisz if (a). Jeśli miałeś na myśli a = true, to ifstwierdzenie jest zbędne.
dan04
1
Szczegółowość w anonimowych klasach Java. Mam nadzieję, że wkrótce zostanie naprawiony.
structPointer->memberw C / C ++. Może być dobry do czytania kodu innej osoby, ale mi się nie podoba. Dwie postacie zamiast jednej ... co za strata miejsca!
Niestety należy go odróżnić od tego ., co dotyczy członków obiektu niebędącego wskaźnikiem. Niejednoznaczna składnia jest zła, mmmkay?
greyfade
2
@greyfade: Tak! Ponieważ kompilator nie może użyć reguł systemowych typu, aby określić, kiedy używasz typu wskaźnik do struktury i zastosować dereferencję niejawnie. Nie, to szalone gadanie! (A jednak wciąż może dać ci komunikat o błędzie, gdy się pomylisz.) W składni nie ma nic dwuznacznego. Jak zwykle C jest bałaganem Braindead. Delphi ma ukryte dereferences dobrze, jeśli faktycznie działa w ciemnych kątach, które wymagają wskaźniki do rekordów, dzięki czemu może z pewnością być wykonane bez mylące parser ...
Mason Wheeler
5
@Mason: Co z przypadkami takimi shared_ptr, jak ->dostęp do zawartego typu i .dostęp do właściwości shared_ptrsamego siebie? Przepraszam, ale zupełnie się nie zgadzam.
Billy ONeal,
2
mogło być gorzej. Może to być PHP, w którym musisz ->uzyskiwać dostęp do członków czegokolwiek .
Carson Myers,
1
@maaartinus: Każdy kod, który opiera się w dużej mierze na nieoczywistej kolejności operacji, nie jest kodem, który napiszę.
Billy ONeal
0
Wieloliniowy kod Scala w nawiasach
Na przykład:
class Foo(
val bar: String,
val baz: Int,
val bing: String,
val bong: Boolean
) extends Model {
// body here
}
To, co tak naprawdę zyskujesz, jest wspaniałe. Generuje dla ciebie konstruktor oraz funkcje pobierające i ustawiające. Ale z pewnością jest brzydka i łamie wszystkie moje mentalne modele wcięcia kodu i po prostu sprawia, że mam wrażenie, że jestem w dziwnej kanapce z Javą z jednej strony i Lisp z drugiej. (Och, czekaj ... to raczej cel Scali.)
Jestem zdezorientowany - czy masz na myśli część w nawiasie ( val bari tak dalej) czy część w nawiasach klamrowych (część następna extends Model)? (W tym kodzie nie ma nawiasów)
Billy ONeal
3
Część w nawiasach. Jestem Anglikiem. Nazywamy je nawiasami, do cholery, ponieważ w tej sytuacji nie pełnią nawiasowej roli.
Odpowiedzi:
Wstawianie średnika w JavaScript.
Tak naprawdę nie gryzło mnie to często, ale to tak fenomenalnie zły pomysł, że kręci mi się w głowie.
Oto zasady (z ECMA-262 sekcja 7.9)
Przykład:
źródło
Składnia Java-bean z powodu braku właściwości C #
GAH !!!
Mam z tym problemy
getX
,getY
,getZ
,getAnotherAnnoyingField
,getWhyIHateJavaBeans
,getThisIsVerbose
,getGAH
... ah tam to jesthashCode
.źródło
public
. Członkowie powinni być prywatni i powinni być rozsądnie manipulowani przez klasę za pomocą logiki wyższego poziomu, a nie za pomocą programów pobierających i ustawiających z kodu klienta.Czułość białych znaków.
Python denerwuje mnie pod tym względem. To znaczy, ja wciąć właściwie w każdym razie, ale robaki mi, że powinienem mieć do. Irytują mnie włączenie prezentacji do składni.
źródło
switch
Oświadczenie (w C, C ++, C #, Java, itd.)Oto przykład, dlaczego uważam to za bardzo niewygodne:
Nie kompiluje się, ponieważ zmienna
i
jest ponownie zadeklarowana w tym samym zakresie. To wydaje się drobnym szczegółem, ale bardzo często mnie gryzie. Mogę dodawać nawiasy klamrowe, aby je złagodzić, ale byłoby miło, gdyby nawiasy klamrowe były obowiązkową częścią składni i nie było zbędnego dodatkowego poziomu wcięcia. Naprawdę nie lubię też pisać dodatkówbreak
. Byłoby to o wiele ładniejsze:To sprawia, że wygląda bardziej jak łańcuch
if
/else
, co jest dobre, ponieważ jest również semantycznie podobne. Przynajmniej w języku C # nie byłoby to jednak to samo, ponieważ wswitch
instrukcji kolejność etykiet wielkości liter nie ma znaczenia, ale wif
/else
ma to znaczenie.źródło
goto
podobnego lub podobnego), jak ma to już miejsce w języku C #.case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;
.break
był domyślny i trzeba było określić tylko upadek. Nie musisz już tego komentować! :)Deklaracje tablic w VB.NET
Zawsze udaje mi się zapomnieć, że inicjując stałe tablice w VB.NET, określasz górną granicę tablicy, a nie liczbę elementów, jak w C / C ++, PHP czy Java. Poza VB6 (tam nie pojedziemy ...) nie mogę wymyślić innego języka, który robi to w ten sposób:
źródło
VB6 - Oddzielna deklaracja i przypisanie zmiennych
Większość języków pozwala zadeklarować zmienną i przypisać ją w jednym wierszu kodu; Z drugiej strony VB6 zmusza cię do użycia dwóch.
Możesz użyć dwukropka, aby umieścić dwa polecenia w jednym wierszu, ale szybko zamienia się w rzeczywisty kod.
źródło
Dim Hurp As New Collection
, jeśli uzyskasz dostęp,Hurp
gdy odnosi się doNothing
niego, zostanie on magicznie zainicjowany przed dostępem. Jeśli wyraźnie go ustawiszNothing
i dotkniesz go ponownie, zostanie wskrzeszony ... sapie!Komentowanie w CSS
//
nie komentuje wierszy kodu, jak ma to miejsce w wielu innych językach, takich jak PHP i JavaScript. Chociaż/* this is commented out */
działa, wolę używać//
.Jest to uciążliwe, ponieważ w połowie przypadków zapominam, że edytuję CSS, a następnie muszę wrócić i naprawić błąd.
źródło
PHP - spójne porządkowanie argumentów
PHP ma wiele przydatnych funkcji do wykonywania praktycznie każdej operacji, o której można pomyśleć na tablicy lub łańcuchu. Wiele z tych operacji wymaga użycia zarówno a, jak
$needle
i a$haystack
, ale różne funkcje przyjmują je w różnych kolejności. Która funkcja wymaga, które argumenty są jednym z tych faktów, których mój mózg nie chce przyswoić, bez względu na to, jak często je spotykam!Weź funkcje in_array i strstr :
Co zabawne, PHP wydaje się być wewnętrznie spójne z tymi porządkami, ponieważ wszystkie funkcje łańcuchowe wydają się używać,
$haystack, $needle
podczas gdy funkcje tablicowe są na odwrót, ale może to trochę przyzwyczaić się dla kogoś nowego w PHP. W ExpressionEngine jest dobry post, który mówi o tym dziwactwie bardziej szczegółowo, a także dyskusja na liście błędów PHP , która zawiera bardzo krótką odpowiedź od zespołu PHP!źródło
$needle
,$haystack
ponieważ przypomina sposób na znalezienie igły w stogu siana .strstr
. Tak pięknie bez znaczenia.Pyton
self
parametr w definicjach metod instancjiźródło
self
zdarza się łatwo i kosztuje czas.Jawa
Kropka. Kropka. Koniec opowieści.
Gdzie zacząć? Och, wiem od czego zacząć: niesamowicie skomplikowana i brzydka, głupia i z natury zepsuta Java . Czy muszę powiedzieć więcej? :( Ok dobrze, a następnie: wpisz kasowanie .
Potem jest niedeterministyczne zarządzanie zasobami. Kewl footcher!
Co dalej? O tak: Głupie wyrażenia Javy to moja najbardziej irytująca, kipiąca wołowina. Nie mogę zliczyć, ile razy mnie nie było, ponieważ nie miałem wystarczającej liczby ukośników. Jest to nawet gorsze niż brak dostępu do jakichkolwiek właściwości Unicode z tego tysiąclecia - co jest całkowitym bykiem. Dziesięć cholernych lat nieaktualnych !!! Kompletnie bezużyteczny. Wyrzuć to.
Następnie jest błąd polegający na tym, że skróty klas postaci nie działają na nie-ASCII. Co za królewski ból! I nawet nie rozważaj używania
\p{javaWhiteSpace}
; nie robi to dobrze z kilkoma bardzo powszechnymi punktami kodowymi spacjami w Unicode.Czy wiesz, że jest
\p{javaJavaIdentifierStart}
nieruchomość? Co oni sobie myślą? Tak się cieszę, że mają tak inteligentnych podglądaczy na twardo.Czy kiedykolwiek próbowałeś użyć flagi CANON_EQ? Czy wiesz, że to naprawdę działa, a czego nie robi? Co powiesz na tak zwaną „przypadek Unicode”? Kilka normalnych obudów po prostu w ogóle nie działa.
Potem utrudniają pisanie możliwych do utrzymania wyrażeń regularnych. Java wciąż nie wymyślił, jak pisać ciągi wielowierszowe, więc w końcu piszesz takie szalone rzeczy:
Co to są te wszystkie nowe linie? Och, tylko głupota Java. Używali komentarzy Perla, a nie komentarzy Javy ( idioci! ), Które przechodzą do końca linii. Więc jeśli nie umieścisz ich
\n
tam, odetniesz resztę swojego wzoru. Duh i double duh!Nie używaj wyrażeń regularnych w Javie: po prostu skończysz z chęcią zniszczenia rzeczy, wszystko jest tak bolesne i zepsute. Nie mogę uwierzyć, że ludzie to znoszą. Niektórzy nie .
Następnie możemy zacząć mówić o idiotycznych nonsensach Javy za pomocą kodowania. Po pierwsze, domyślnym kodowaniem platformy jest zawsze słabe 8-bitowe kodowanie, mimo że znaki Java są Unicode. Jest też sposób, w jaki nie zgłaszają wyjątku dotyczącego błędu kodowania. Gwarantujesz bzdury. A może to:
Co za różnica? Czy wiesz, że tylko jeden z nich zgłosi wyjątek, jeśli wystąpi błąd kodowania? Reszta po prostu kaganiec.
Potem idiotyzm znaków Java nie wystarcza do utrzymania postaci! Co oni do diabła myślą? Dlatego nazywam je charcharami. Musisz napisać taki kod, jeśli spodziewasz się, że działa poprawnie:
A kto kiedykolwiek myśli, aby to zrobić? Obok nikogo.
Ile tam jest znaków
"\uD83D\uDCA9"
? Jeden lub dwa? Zależy jak je policzysz. Silnik regex oczywiście zajmuje się znakami logicznymi, więc wzorzec^.$
się powiedzie, a wzorzec^..$
się nie powiedzie. Owo szaleństwo zostało pokazane tutaj:Ten idiotyzm polega na tym, że nie możesz napisać całkowicie rozsądnego
\u1F4A9
, ani oczywiście nie otrzymujesz ostrzeżenia, że nie możesz tego zrobić. Po prostu robi to źle.Głupiutki.
Skoro już o tym
\uXXXX
mowa, cała notacja jest wrodzona martwa dla mózgu. Preprocesor Java ( tak, słyszałeś mnie ) dotrze do niego, zanim zrobi to Java, więc nie wolno ci pisać całkowicie rozsądnych rzeczy, takich jak"\u0022"
, ponieważ zanim Java to zobaczy, jego preprocesor zmienił go"""
, więc przegrywasz. Och, czekaj, nie, jeśli to wyrażenie regularne! Możesz więc dobrze wykorzystać"\\u0022"
.Riiiiiiiight!
Czy wiesz, że w Javie nie ma możliwości wykonania
isatty(0)
połączenia? Nie wolno ci nawet myśleć takich myśli. To nie byłoby dla ciebie dobre.A potem jest cała obrzydliwość klasy.
Lub fakt, że nie ma sposobu, aby określić kodowanie pliku źródłowego Java w tym samym pliku źródłowym, aby go nie zgubić? Po raz kolejny żądam wiedzieć: CO CHCĘ BYŁO MYŚLENIE‽‽‽
Powstrzymać szaleństwo! Nie mogę uwierzyć, że ludzie znoszą te śmieci. To kompletny żart. Wolałbym być powitaniem Walmarta niż cierpieć z powodu procy i strzały oburzającego szaleństwa na Jawie. Wszystko jest zepsute i nie tylko nie mogą tego naprawić, ale nie naprawią tego.
To przez tych samych winorośli, którzy szczycili się językiem, w którym
printf()
funkcja była nielegalna . Ojej, to na pewno zadziałało naprawdę, prawda ?!Zwykłe zdrętwiałe czaszki. Policzkowanie suk jest dla nich zbyt miłe. Gdybym chciał zaprogramować w asemblerze, zrobiłbym to. To nie jest język do ocalenia. Cesarz nie ma ubrania.
Nienawidzimy tego. Nienawidzimy tego na zawsze . Niech umrze umrze umrze !
źródło
^H
) :)Składnia deklaracji wskaźnika funkcji w C i C ++:
Deklaruje on wskaźnik funkcji o nazwie,
f
którego pointee może zająć dwaint
si zwrócić anint
.Wolałbym taką składnię:
Powiedzmy, że chcesz zadeklarować wskaźnik funkcji
g
, której wskazywany może przybrać dwieint
s oraz funkcję odint
iint
doint
, i zwrócićint
.W notacji C lub C ++ zadeklarujesz ją jako:
Dzięki powyższej notacji to samo można zadeklarować jako:
Później jest o wiele bardziej intuicyjny IMO.
Poza tym: język programowania o nazwie OOC naprawia tę składnię (i różne inne problemy składniowe w C i C ++). Sprawdź jego stronę główną tutaj .
źródło
Szczegółowość w Javie.
to znaczy:
źródło
const int
na przykład.a+(b*c)/d*e+f/g^20
używającBigInteger
w Javie. Dlaczego ten język nie pozwala na przeciążanie operatora?\ my \ wouldnt \ fix \ our \ parser namespace w PHP
Składnia jest nie tylko brzydka, ale prowadzi do zamieszania, gdy nowi programiści muszą myśleć o przestrzeniach nazw w łańcuchach. (PHP interpoluje ukośniki odwrotne w ciągach podwójnie cytowanych jako sekwencje specjalne. Próba reprezentowania przestrzeni nazw jak
\you\should\never\do\that
w ciągach podwójnych zamiast ciągów pojedynczych doprowadzi do znaków nowej linii, tabulatorów i katastrofy.)źródło
Nienawidzę faktu, że nawiasy klamrowe mogą być opcjonalne po instrukcji if / while / for.
Zwłaszcza gdy widzę kod podobny do
Proszę po prostu włożyć szelki i gotowe.
źródło
for (...) while (...) if (...) { x(); y(); }
lepiej jest przepisać, jakfor (...) { while (...) { if (...) { x(); y(); } } }
oczywiście przy odpowiednim wcięciu.VBScript nie ma operatorów logicznych
W przeciwieństwie do prawie każdego rozsądnego języka, VBScript używa operatorów bitowych zamiast operatorów logicznych. Co to oznacza w praktyce? Cóż, jak zauważa Eric Lippert :
i
NIE są takie same w VBScript!
Co gorsza, choć oznacza to, że nie ma oceny zwarcie w VBScript dlatego poniższe oświadczenie będzie rozbić swój program, jeśli
Blah
jest w stanieNothing
Zgadza się, VBScript oceni obie części porównania AND, nawet jeśli pierwsza jest fałszywa! Po prostu pozwól temu zatonąć ...
źródło
If x Then ... If Not x Then ... End If ... End If
i zorientujesz się, że x wynosi 2, tak naprawdę nie programowałeś w VB / VBScript.EDYCJA: Po dyskusji w komentarzach postanowiłem zaktualizować tę odpowiedź, aby lepiej się wyjaśnić.
Naprawdę nie znoszę wyglądu wskaźników funkcji w C. Zwykle każda deklaracja zmiennej wygląda jak krotka:
type varname;
Z drugiej strony deklaracje wskaźnika funkcji wyglądają jak deklaracja funkcji z * przed nazwą funkcji. Mogę zaakceptować to jako opis typu wskaźnika, ale w C deklaruje zarówno typ, jak i nazwę zmiennej tego typu. Wydaje mi się to niespójne, ponieważ deklaracje typów różnią się od deklaracji zmiennych.struct myStruct{int X; int Y;}
definiuje tylko typ, nie definiuje zmiennej o nazwiemyStruct
. Podobnie nie widzę powodu, aby deklaracje typów i deklaracje zmiennych były grupowane w jedną instrukcję atomową we wskaźnikach funkcji, ani też nie doceniam odchylenia odtype varname;
struktury.Ktoś zauważył, że jest to zgodne z pewną regułą spiralną i może tak być, ale cechą dobrej składni jest to, że jest ona oczywista, a jej wewnętrzna logika jest oczywista. Reguła spiralna nie jest w żaden sposób oczywista.
źródło
typedef
.Średniki w VBScript - lub ich brak
Cały dzień pracuję w językach, które oczekują średników na końcu każdej linii. Dodaj jeden na końcu wiersza w VBScript, a Twój kod nie będzie już działał.
źródło
Argumenty wejścia / wyjścia. Jestem za argumentami (dobrze, że jestem), nasze argumenty też są w porządku, ale argument, który musi przekazać te dwa stany, wkurza mnie.
To, co tu celuję, to funkcje, które pobierają dane wejściowe z parametru, a następnie nadpisują je danymi wyjściowymi. Można przekazać obiekt przez odniesienie, aby go zaktualizować. Ale, głównie w przypadku typów pierwotnych, zabranie obiektu, użycie go, a następnie całkowita zmiana, nie jest dla mnie właściwe. Nie powinieneś zmieniać znaczenia argumentu poprzez inout.
źródło
in
nain
argumentach albo, ja mówię tylko o nich. Ponadto, moim zdaniem, nic nie może usprawiedliwić argumentu wejścia / wyjścia, a ich wyraźne nie łagodzi bólu. Nie powinno być żadnego powodu, aby inicjalizować zmienną lokalną wartością pomocną dla funkcji i mieć tę samą zmienną, która nagle zawiera wszystko, co funkcja postanowiła tam umieścić. Te dwa powinny być różne. Zawsze.struct
którym nowa wartość zależy od wartości innego pola tego samegostruct
.)class
obiektów w C #) modyfikowane przez funkcję są dla mnie w porządku. Pomijając, że nie lubię stałe przypisać struktury, mijającstruct
przyref
słowo kluczowe aby zaktualizować to jest w porządku, zbyt. Naprawdę nienawidzę, gdy dane wejściowe są nadpisywane danymi wyjściowymi. Najlepszym przykładem, jaki mogę wymyślić, jestaccept
funkcja gniazda Berkeley : potrzebujesocklen_t*
argumentu, który na wejściu musi zawierać rozmiarstruct sockaddr*
przekazanego; a na wyjściu będzie zawierać liczbę bajtów, które zostały do niego zapisane. To powinno być kryminalne.Deklaracje tablicowe w C i C ++.
Zazwyczaj deklaracja zmiennej ma format
type variable_name
. Możesz łatwo odczytać te deklaracje w sposób od lewej do prawej. Aleint foo[size]
na początku wygląda na to, że deklaruje sięfoo
jako liczbę całkowitą, a potem czytasz dalej i widzisz tego typu „tablica liczb całkowitych”.int[size] foo
czyta znacznie lepiej.I ja też cierpię, kiedy programiści zadeklarować wskaźniki takie jak to z podobnego powodu:
int *foo
. Z jakiegoś powodu nie zorientowałem się, że jest to typowy sposób, w jaki jest napisany.źródło
int* a, b;
* nie deklarujea
ib
jako wskazówki; tylkoa
jest. Dlatego lepiej jest napisać to jakoint *a, b;
(lub nawet lepiej napisać je jako dwie deklaracje).*
że nie wiąże się z typem.void(int) *f;
? Nie:void (*f)(int);
int* a, b;
że wspomniany przez ciebie problem jest znacznie bardziej skandaliczny.Nadmiarowa parametryzacja w Javie:
Co drugi typ parametryzacji kompilator myśleć
foo
może mieć?źródło
HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
HashMap<String,HashMap<String,String>> foo = new HashMap<>();
What other type parameterization does the compiler think foo could have?
- Bez względu na powód, dla którego to jest typ surowy - tak jakby ktoś przy zdrowych zmysłach miksowałby typy surowe i sparametryzowane.Ponieważ ludzie już narzekali na
=
vs.==
, pozwól mi wskazać znacznie gorszą alternatywę. PL / Miałem jedno:=
i drugie=
, ale gdy coś było „oczywiście” zadaniem, pozwoliłoby ci to uniknąć korzystania=
z niego. Użycie:=
pozwala zmusić coś do przypisania w sytuacji, w której kompilator inaczej interpretowałby to jako porównanie.Niestety kompilator nie zawsze decydował o tym, czego można się spodziewać. Rozważ tylko jeden oczywisty przykład:
Teraz, dla większości osób znających większość „zwykłych” języków, znaczenie tego jest dość oczywiste - przypisz 0 zarówno A, jak i B. PL / I jest tylko trochę… inny. Z powodów znanych tylko (szalonym) projektantom języka pierwszy
=
jest interpretowany jako zadanie, ale drugi=
jest interpretowany jako porównanie. Dlatego porównuje B do 0, a następnie przypisuje wynik tego porównania do A (zgodnie z konwencją typu C, że „fałsz” powoduje 0 i „prawda” w 1).Tak więc, jeśli B było 0, to A staje się 1. W przeciwnym razie A staje się 0. Innymi słowy, zamiast przypisywać tę samą wartość A i B, to faktycznie gwarantuje, że A nie może mieć takiej samej wartości jak B.
Podsumowując: chociaż styl C / C ++ / PHP początkowo wydaje się być bólem, alternatywa jest znacznie gorsza 1 .
1 Cóż, technicznie rzecz biorąc, istnieje inna alternatywa: styl Pascala, gdzie
=
zawsze oznacza, że porównanie i przypisanie zawsze wymaga:=
. Po pewnym czasie korzystania z tego jest dość oczywiste (przynajmniej dla mnie), że przypisanie jest o wiele bardziej powszechne niż porównanie, że jeśli będziesz potrzebować dodatkowych „rzeczy” w celu ujednolicenia tych dwóch, zdecydowanie powinieneś zachować zadania czyste i proste i wymagają dodatkowego „grunge” przy porównaniach, a nie odwrotnie.źródło
==
do równości i:=
do zadania. W ten sposób masz więcej do pisania, ale unikanie samotności=
pomaga uniknąć błędów.Perl
if($x < 10) do_something();
. W tej chwili musisz napisać to jako jednodo_something() if($x < 10);
lub drugieif($x < 10) { do_something(); }
.źródło
do_something() if ($x < 10);
nie jest tak źle.if(..) ...
rozruch, ponieważ wszystkie wyrażenia można ustawić po prawej stronie. Ale są chwile, które naprawdę chcę powiedziećif($x < 10) do_something();
, i to niefortunne, że Perl mi na to nie pozwala.if ($x<10) do_something(); and_call_me();
a potem nie zastanawiasz się, dlaczego nigdy nie dostajesz telefonu. Chciałbym, żeby C i rodzina potrzebowali nawiasów klamrowych, aby zapobiec tego rodzaju błędom.else
s. (Chciałbym, żeby było takEXPR1 if COND else EXPR2
jak Python)reinterpret_cast<unsigned long>
w c ++. Ta operacja jest przydatna w radzeniu sobie z zagranicznymi interfejsami API i zapewnianiu precyzji liczbowej, dlaczego pisanie i tak brzydki jest taki trud?źródło
reinterpret_cast
w C ++ jest bardzo silnym zapachem kodu. W 99% przypadków, kiedy masz zamiar go użyć, są szanse, że nie powinieneś - prawdopodobnie zrobiłeś coś złego. Pozostały 1% czasu łączysz się z C.reinterpret_cast
łamie system pisma, aby coś działało, gdy inaczej by nie było. To zwykle zła rzecz.Konstrukcja for ... w JavaScript i konstrukcja foreach w PHP podczas zapętlania tablic. Oba ułatwiają pisanie błędów niż poprawny kod.
źródło
Wskaźniki tablic lub tablice wskaźników w C / C ++. Nadal jestem tym zdezorientowany.
źródło
int[]*
jest wskaźnikiem do tablicy liczb całkowitych iint*[]
jest tablicą wskaźników do liczb całkowitych. Działa również dobrze zconst
s:int* const
jest stałym wskaźnikiem do liczb całkowitych, natomiastconst int*
iint const*
jest wskaźnikami do stałych liczb całkowitych (lub stałych liczb całkowitych).int (*p)[10];
deklaruje,p
że jest wskaźnikiem do tablicy 10 liczb wewnętrznych. Jeślisizeof (int) == 4
, top++
przejdziep
do 40.Fakt, że Python opiera się na formatowaniu tekstu.
źródło
JavaScript / Java itp., To porównanie, np. If (a == 1)
Ile razy piszę, jeśli (a = 1)?
Jako człowiek doskonale to rozumiem. Ale cholerny interpreter / kompilator mówi: „hej, przypiszę 1 do a, następnie sprawdź, czy a jest równe 1, i czy uważasz, że tak!
Wbija mnie w ścianę.
if (a == 1) jest znacznie mniej czytelny, a interpreter / kompilator powinien wiedzieć, co mam na myśli; wiele innych mniejszych języków (VB) opracowuje je z powodzeniem od setek lat.
źródło
if (a = true)
znaczy?if (a == true)
, po prostu napiszif (a)
. Jeśli miałeś na myślia = true
, toif
stwierdzenie jest zbędne.Szczegółowość w anonimowych klasach Java. Mam nadzieję, że wkrótce zostanie naprawiony.
źródło
structPointer->member
w C / C ++. Może być dobry do czytania kodu innej osoby, ale mi się nie podoba. Dwie postacie zamiast jednej ... co za strata miejsca!źródło
.
, co dotyczy członków obiektu niebędącego wskaźnikiem. Niejednoznaczna składnia jest zła, mmmkay?shared_ptr
, jak->
dostęp do zawartego typu i.
dostęp do właściwościshared_ptr
samego siebie? Przepraszam, ale zupełnie się nie zgadzam.->
uzyskiwać dostęp do członków czegokolwiek .Wieloliniowy kod Scala w nawiasach
Na przykład:
To, co tak naprawdę zyskujesz, jest wspaniałe. Generuje dla ciebie konstruktor oraz funkcje pobierające i ustawiające. Ale z pewnością jest brzydka i łamie wszystkie moje mentalne modele wcięcia kodu i po prostu sprawia, że mam wrażenie, że jestem w dziwnej kanapce z Javą z jednej strony i Lisp z drugiej. (Och, czekaj ... to raczej cel Scali.)
źródło
val bar
i tak dalej) czy część w nawiasach klamrowych (część następnaextends Model
)? (W tym kodzie nie ma nawiasów)