Який синтаксичний елемент ви найбільше ненавидите в мові програмування, якою ви часто користуєтесь? [зачинено]


27

Незалежно від того, наскільки ви любите мову програмування, в ній завжди є кілька деталей, які не такі приємні, як вони могли б бути.

У цьому питанні я хотів би конкретно зупинитися на елементах синтаксису. У мові програмування, яку ви часто використовуєте (можливо, ваша улюблена мова програмування або, можливо, та, яку ви змушені використовувати на роботі), який елемент синтаксису ви вважаєте найбільш нечитабельним, незрозумілим, незручним чи неприємним?


@Nathan Taylor, не з цього питання, а з іншого питання .
finnw

Це питання було змінено? Тому що, коли я відповів, це було не зосереджено на "синтаксичних елементах" ... мені доведеться зараз модифікувати свою відповідь.
Талві Ватія

@Talvi: Ні, мова йшла про синтаксис з самого початку.
Тімві

@ Тимві дивно, тоді це повинен бути випадок "відповіді на питання, думаючи, що це було інше".
Талві Ватія

Якщо ви можете проголосувати і вважаєте, що це корисне питання або у вас є корисні відповіді нижче, будь ласка, проголосуйте. Сайтам StackExchange потрібні голоси, щоб створити хорошу спільноту. Ви можете дати 30 голосів на день, не витрачайте їх. Спеціально користувачі з високою репутацією та низьким підрахунком голосів, будь ласка, прочитайте це: meta.programmers.stackexchange.com/questions/393/…
Maniero

Відповіді:


39

Вставка крапки з комою в JavaScript.

Мене насправді мене не кусали часто, але саме така феноменально погана ідея змушує мою голову крутитися.


Ось правила (з ECMA-262 Розділ 7.9)

  1. Коли програма містить маркер, який не дозволений формальною граматикою, то вводиться крапка з комою, якщо (а) в цій точці є розрив рядка, або (b) несподіваний маркер був заключним дужкою.
  2. Коли кінець файлу досягнуто, якщо програма не може бути розібрана інакше, то вставляється крапка з комою.
  3. Коли зустрічається "обмежене виробництво" і містить термінатор рядка в місці, де граматика містить примітку "[тут немає LineTerminator]", то вставляється крапка з комою.

Приклад:

return 1; // returns 1

return
1; // returns undefined


Так, багато хто очікує, що JavaScript є "мовою вільної форми", але це не так.
Андреас Рейбранд

13
Це має сенс, як тільки ви зрозумієте, що JavaScript був розроблений для створення HTML, який також має довгу історію спроб інтерпретувати те, що ваш код "насправді означає", коли він не синтаксично дійсний. (Знайдіть Принцип стійкості колись - найбільша катастрофа в історії обчислень.)
Мейсон Уілер

7
Ці типи помилок, як на мене, є кодовим запахом, який програміст неохайний і ніколи не працював із більшістю формальних "суворих" мов, які, як правило, спричиняють синтаксичну помилку для залишення крапки з комою.
Талві Ватія

7
Wohoo, нарешті хтось, хто також вважає Принцип надійності, - це катастрофа, яка зробила HTML суттєвим безладом, що це є.
Роман Старков

39

Синтаксис Java-bean через відсутність властивостей 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 !!!

Питання у мене з цим

  • Занадто багато коду - Майте документально зафіксоване поле, метод документа, який є задокументованим, та метод сеттера, який задокументований. Цей надзвичайно базовий приклад містить 20 рядків коду для однієї властивості
  • Захаращує списки методу - «Дозволь мені знайти цей метод, руку на: getX, getY, getZ, getAnotherAnnoyingField, getWhyIHateJavaBeans, getThisIsVerbose, getGAH... ах там, hashCode.
  • Документація з декількох областей призводить до поганої, застарілої або відсутньої документації - дратує, коли намагаються зрозуміти, що робить код
  • Тож набридливій третій стороні довелося придумати плагін, щоб зробити це легко - Spoon , Shark , серед інших.

9
Ще раз, коли код настільки багатослівний, що йому потрібні інструменти автоматичного генерування, щось не так. Я хлопець NetBeans, але він також має можливість автоматично генерувати геттери та сетери. Але Javadoc випадає з syn, він все ще багатослівний, він все ще захаращує javadoc тощо.
TheLQ

11
Якщо вам потрібні геттери на все, то з клієнтським кодом щось не так .
finnw

7
Отримання геттерів та сетерів порушує інкапсуляцію. Поле також може бути public. Учасники повинні бути приватними, і їх слід розумно маніпулювати класом з логікою вищого рівня, а не з геттерами та сетерами з клієнтського коду.
greyfade

6
@greyfade: Якщо він відкритий, ви не можете легко змінити те, що робить код налаштування (вам доведеться змінити весь код, який встановлює поле ззовні).
Барт ван Хекелом

3
@SHiNKiROU: Java виглядає чистою? Я ніколи цього не чув! Моя головна боротьба з Java - це той факт, що, здавалося б, проста річ займає десятки рядків коду, які мені потрібно подумки ігнорувати.
конфігуратор

33

Чутливість пробілу.

Python мене дратує в цьому відношенні. Я маю на увазі, я все одно правильно відступаю, але це клопоче про те, що мені потрібно було б. Зробити презентаційну частину синтаксису мене дратує.


8
ви навчитеся любити це
user10008

2
синтаксис - презентація
Вінстон Еверт

32

switchЗаява (в C, C ++, C #, Java і т.д.)

Ось приклад, чому я вважаю це дуже незручним:

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

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

Це не компілюється, оскільки змінна iпередекларована в тій же області. Це здається незначною деталлю, але мене кусає насправді часто. Я можу додати фігурні дужки, щоб пом'якшити це, але було б добре, якби фігурні дужки були обов'язковою частиною синтаксису, і не було зайвого додаткового рівня відступу. Я також дуже ненавиджу писати додаткове break. Це було б набагато приємніше:

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

Це робить його схожим більше на ланцюг if/ elseланцюг, що добре, оскільки він теж семантично схожий. Принаймні, в C # все одно це не буде тим самим, тому що в switchзаяві порядок міток справи не має значення, але в an if/ elseit does.


1
На жаль, ваш покращений синтаксис не усуває те, що є, мабуть, найбільшою особливістю комутатора у більшості з цих мов: Прохідне. "Пристрій Даффа" в C - прекрасний приклад значення цієї конкретної "неправильної функції". У мовах, подібних до С, також часто застосовується пропуск у перекладачах та подібних програмах.
greyfade

7
Ні, це не усуває. Потрібно лише зробити його більш чітким (використовуючи gotoабо подібне), як це вже є у C #.
Тімві

8
@greyfade: Будь-який код, що використовує пристрій Даффа на C, повинен померти жахливою смертю. Компілятори приймають кращі рішення щодо таких речей, ніж ви.
Біллі ONeal

4
@greyfade: Delphi отримує навколо проблеми множинного значення, просто дозволяючи кілька індексів в разі: case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;.
Френк Ширар

3
@jkerian: Тепер уявіть, що breakза замовчуванням було вказано лише пропуск. Більше не потрібно пам'ятати, щоб коментувати це! :)
Тімві

27

Декларації масиву у VB.NET

Мені завжди вдається забути, що при ініціалізації фіксованих масивів у VB.NET ви вказуєте верхню межу масиву, а не кількість елементів, як у C / C ++, PHP або Java. Крім VB6 (ми туди не підемо ...), я не можу придумати іншої мови, яка робить це так:

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

Я думаю, що всі мови BASIC роблять це ... Я знаю, що вони є початковими BASIC і QBasic.
Майкл К

OMG, що справді жахливо .... +1
mikera

25

VB6 - Окрема змінна декларація та призначення

Більшість мов дозволяють вам оголосити змінну та призначити її в одному рядку коду; З іншого боку, VB6 змушує вас використовувати два.

Dim i as Integer
i = 0

Dim derpderp as Collection
Set derpderp = new Collection

Ви можете використовувати двокрапку, щоб поставити дві команди в один рядок, але це швидко стає безладним у фактичному коді.

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

7
+1 за необхідність використання VB6 як вашої найчастішої мови.
Вальтер

9
Я використовую його щодня..соб.
systempuntoout

Чи не має Паскаль подібний синтаксис? Я завжди думав, що це противно.
greyfade

1
Є особливий випадок: якщо ви Dim Hurp As New Collection, якщо ви Hurpзвертаєтесь до Nothingнього, коли він посилається , він буде магічно ініціалізований перед доступом. Якщо ви явно встановили йогоNothing і знову торкнетесь, воно почне воскрешати ... задихайтесь!
Джефрі Хантін

1
+ 1 млн. За Дерп. Derp de derp de tiddly tum de derp.
MVCylon

24

Коментування в CSS

//не коментує рядки коду, як це робиться у багатьох інших мовах, як PHP та Javascript. Хоча /* this is commented out */працює, я вважаю за краще використовувати //.

Це неприємно, тому що половину часу я забуваю, я редагую CSS, а потім доведеться повертатися назад та виправляти помилку.


У цей день і вік ви могли б подумати, що необроблений CSS вважатиметься об'єктним кодом.
Том Хотін - тайклін

// працює чудово, щоб прокоментувати CSS. Я роблю це постійно. Все, що я справді роблю, - це набирати сміття. але, здається, працює, пропускаючи нерозбірливу лінію.
MVCylon

1
@MVCylon Якщо ви використовуєте // для коментування рядка, все після цього наступного рядка також пропускається. {всередині цього конкретного стилю} Іншими словами, це НЕПРИЄМО, тому що ці рядки не слід пропускати.
Талві Ватія

20

PHP - послідовне впорядкування аргументів

PHP має ряд зручних функцій для виконання майже всіх операцій, які ви могли б придумати на масиві або рядку. Для багатьох цих операцій потрібно використовувати як a$needle і a $haystack, але різні функції приймають їх у різному порядку. Яка функція вимагає, які аргументи є одним із тих фактів, який мій мозок відмовляється засвоювати, незалежно від того, як часто я стикаюся з ними!

Візьміть функції in_array та 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])

Як не дивно, схоже, що PHP внутрішньо узгоджується з цими впорядкуваннями в тому, що всі рядкові функції, здається, використовуються, $haystack, $needleколи функції масиву є навпаки, але це може зайняти трохи звикання до когось нового в PHP. В ExpressionEngine є хороший пост, де детальніше про цю конкретну хитрість розповідається, а також обговорення у списку помилок PHP , де представлена ​​дуже коротка відповідь від команди PHP!

helly@php.net Тоді
використовуйте гідний IDE.

2
Простіше запам’ятати порядок $needle, $haystackоскільки він нагадує спосіб сказати знайти голку в копиці сіна .
kiamlaluno

3
Підказка: у функціях масиву голка виходить на перше місце. у рядових функціях сіно стоїть на першому місці.
GSto

17
Я люблю ім'я strstr. Так гарно безглуздо.
конфігуратор

5
Просто прочитайте пов'язаний запис у програмі PHP's bugtracker. Серйозно, wtf? o Послідовність Imho є вагомим питанням для будь-якого API, і лише відповідь "використовувати гідний IDE тоді" - це просто не вагома відповідь. Принаймні, це могло бути розроблено менш вираженим запальним ефектом з боку дияволів.
Baelnorn

2
Чесно кажучи, те, що мене зводить з розуму від цього, - це те, що це не повинно бути функцією! Це повинен бути просто метод: $ haystack-> find ($ needle). Справу зроблено.
веслування

19

Пітон

self Параметр, наприклад, визначення методу


У методі classs зазвичай називають cls, а використання self суперечить умові.

Це насправді має сенс, якщо ви подумаєте про це. Це те саме, що оголошення приватного методу в інших мовах, параметр self явно явний в python, де він неявний для інших мов. Якщо ви хочете, щоб це було неявним, додайте @classmethod decorator перед оголошенням методу. Див. Docs.python.org/library/functions.html#classmethod . Вивчення деталей того, як це працює, дасть вам деяке уявлення про те, як це робиться на інших мовах неявно.
Еван Плейс

4
Я розумію причини і чому його там залишають neopythonic.blogspot.com/2008/10/…, але мені це все ще не подобається
Горан Перош,

@Evan Plaice: "Параметр" Я "явно явний в python, де він неявний для інших мов" Це лише одна частина історії. Інша частина - пітон, що набирається щотижня. Разом це страшно, забуття selfтрапляється легко і коштує часу.
maaartinus

@maaartinus Потім додайте до методу екземпляра клас декоратора методу. Не має нічого спільного із "слабо набраним". Це просто робить взаємозв'язок між статичними методами / функціями (відсутність параметра "Я") та методами екземпляра (включає "Я") очевидним. Метод екземпляра не знає, що це батьківський клас, якщо ви не дасте йому посилання на це. В інших мовах відмітна характеристика, яку я окреслив, просто прихована за синтаксичним цукром. Якби у мене був вибір зробити це на всьому, я б спершу почав вивчати OOP на Python.
Еван Плейс

18

Java

Період. Повна зупинка. Кінець історії.

З чого почати? О, я знаю, з чого почати: шалено складні, некрасиві та нерозумні, нерозумні і породжені дженерики на Java . Потрібно сказати більше? :( Добре, тоді: введіть стирання .

Тоді є недетерміноване управління ресурсами. Ловець Kewl!

Що далі? О так: дурні реджекси Яви - це моя найприємніша, кипляча яловичина. Я не можу підрахувати, скільки разів мене шлангували, не маючи достатньої кількості зворотних нахилів. Це ще гірше, ніж не мати доступу до будь-яких властивостей Unicode з цього тисячоліття - що є повною мірою. Застаріло десять фрикційних років !!!Зовсім марно. Сміття.

Тоді є помилка, що ярлики класів символів не працюють на не-ASCII. Який королівський біль! І навіть не думайте використовувати \p{javaWhiteSpace}; це не робить все правильно з кількома дуже поширеними кодовими точками пробілу Unicode.

Чи знаєте ви, що є \p{javaJavaIdentifierStart}власність? Про що вони думали? Тож раді, що вони отримали таких розумних улюбленців вуркіна на жорсткій основі.

Ви коли-небудь намагалися використовувати прапор CANON_EQ? Чи знаєте ви, що це насправді , а що він не робить? Як щодо так званого “випадку Unicode”? Купа нормальних речей з корпусом просто не працює.

Тоді їм важко писати рентабельні реджекси. Java досі не розгадала, як писати багаторядкові рядки, тож ви нарешті пишете такі божевільні речі:

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

Що це за ті новинки? О, просто дурість Java. Вони використовували коментарі Perl, а не коментарі Java ( ідіоти! ), Які йдуть до кінця рядка. Тож якщо ви не покладете їх\n там, ви відсікаєте решту своєї схеми. Дух і подвійний дух!

Не використовуйте реджекси на Java: ви просто захочете розбити речі, все так боляче і зламано. Я не можу повірити, що люди мирилися з цим. Деякі ні .

Тоді ми можемо почати говорити про ідіотські дурниці Яви з кодуванням. По-перше, існує той факт, що кодування платформи за замовчуванням завжди є кульгавим 8-бітовим кодуванням, навіть якщо замовниками Java є Unicode. Тоді є те, як вони не створюють винятку щодо помилки кодування. Ви гарантовано отримаєте лайно. А як щодо цього:

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.

Яка різниця? Чи знаєте ви, що тільки один із них створить виняток, якщо у вас є помилка кодування? Решта просто мордочкою їх.

Тоді ідіотизм символів Java недостатній для утримання персонажа! Що, чорт задумали вони? Тому я називаю їх чархарами. Ви повинні написати такий код, якщо очікуєте, що він працює правильно:

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

І хто коли-небудь думає це зробити? Поруч ніхто.

Скільки символів там "\uD83D\uDCA9"? Один чи два? Залежить від того, як ви їх рахуєте. Зрозуміло, що двигун регулярного вирівнювання має справу з логічними символами, тож візерунок ^.$буде успішним, а шаблон ^..$- невдалим. Це божевілля продемонстровано тут:

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.

Цей ідіотизм - це все, тому що ви не можете написати абсолютно розумне \u1F4A9 , і, звичайно, не отримуєте попередження про те, що не можете цього зробити. Це просто робить не так.

Стооопід.

Поки ми перебуваємо на цьому, вся \uXXXXпозначення є вродженим мозком мертвим. Препроцесор Java ( так, ви мене чули ) отримує це ще до того, як зробить Java, тому вам заборонено писати цілком розумні речі на кшталт "\u0022", тому що до того часу, як Java бачить це, його препроцесор перетворив його на """, так що ви програєте. О, зачекайте, не якщо він знаходиться в регексі! Так що ви можете використовувати "\\u0022"просто чудово.

Riiiiiiiight!

Чи знаєте ви, що в Java немає можливості isatty(0)телефонувати? Вам навіть не дозволено думати про такі думки. Це було б не добре для вас.

А тут вся гидота класових.

Або той факт, що немає можливості вказати кодування вихідного файлу Java у тому самому вихідному файлі, щоб ви не втратили його? Я ще раз вимагаю знати: ЩО ПЕКЛО ДУМАЄТЬСЯ? »

Зупиніть безумство! Я не можу повірити, що люди миряться з цим сміттям. Це повний жарт. Я вважаю за краще привітатись до Вальмарта, ніж пережити стропи та стріли шаленого божевілля Яви. Це все зламано, і вони не тільки не можуть його виправити, вони не виправлять.

Це тими самими лисицями-виноградами, які пишалися мовою, яка забороняла printf()функціонувати незаконно . Боже, це впевнено спрацювало добре, хіба це не було !?

Чисті нумбочки. Сучка-плескання для них занадто доброзичлива. Якби я хотів програмувати в асемблері, я б. Це не врятована мова. У імператора немає одягу.

Ми ненавидимо це. Ми ненавидимо це назавжди . Нехай помирає, помирає, помирає !


Ха-ха, хороший, я не чіпаю Java, тому що вона занадто неполірована, як ти описуєш. Щодо \ uD83D ... добре, я вважаю, що кращим способом сказати це є те, що ви скоріше, щоб рядки були не UTF-16, а UTF-32. Якщо ви приймаєте UTF-16-ness, то регулярний вираз зробить правильно; це виклик довжини.
Роман Старков

4
-1. За винятком коментарів у форматі regexp та Unicode, жоден із згаданих вами речей не є елементом синтаксису.
Йорг W Міттаг

3
@ Йорге, ти хочеш синтаксис? Добре: Java дозволяє розміщувати контрольні символи, включати ESC та NUL в ідентифікатори. WTH вони думали ???
tchrist

4
@tchrist: Нічого собі! Якщо я коли-небудь ще раз напишу програму Java, всі мої змінні матимуть імена, що складаються з різної кількості символів ^H
зворотної області

1
@tchrist, відчуваєш себе краще зараз?

16

Синтаксис декларації вказівника функції в C і C ++:

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

Це оголошує покажчик функції з ім'ям, fчий pointee може зайняти два ints та повернути an int.

Я б більше віддав перевагу такому синтаксису:

f: (int, int) => int

Скажімо, ви хочете оголосити покажчик функції, указівник gякого може приймати два ints, а функцію від intі intдо int, і повертати an int.

За допомогою позначення C або C ++ ви оголосите це як:

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

З запропонованими вище позначеннями те саме можна оголосити як:

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

Пізніше набагато інтуїтивніше ІМО.


Убік: мова програмування під назвою OOC виправляє цей синтаксис (та різні інші синтаксичні проблеми в C та C ++). Перегляньте його домашню сторінку тут .


Погодьтеся, деякі "прості C" / "C ++" не підтримують його чи не підтримують його з різним синтаксисом. Спеціальний синтаксис, який допомагає вказувати, коли підтримується функція мови програмування. Тому C # додав синтаксис "делегат".
umlcat

Делегати - це не лише синтаксичний цукор, оскільки вони також зберігають об'єкт (всупереч вказівникам на функції C ++, які мають навіть гірший синтаксис, ніж покажчики звичайних функцій)
Tamás Szelei

14

Багатослівність на Java.

тобто:

public static final int 

6
У порівнянні з? (15
годин

7
Порівняно з: const intнаприклад.
OscarRyz

11
"загальнодоступний статичний фінал int x = 4;" порівняно з "x = 4" в Haskell.
Jared Updike

24
Це не багатослівність. Спробуйте написати з a+(b*c)/d*e+f/g^20використанням BigIntegerв Java. Чому ця мова не дозволяє оператору перевантажуватись?
МАК

4
@Michael: програмісти, яким потрібно захиститись від себе ціною, можуть найкраще захистити себе (і зменшити біль для всіх інших), зовсім не програмуючи: D.
МАК

12

\ ми \ wouldnt \ fix \ наш \ синтаксис простору імен \ парсер у PHP

Синтаксис не тільки потворний, він призводить до плутанини, коли нові розробникам доводиться думати про простори імен в рядках. (PHP інтерполює зворотні косої риски в рядки з подвійним котируванням як послідовності втечі. Спроба зобразити простір імен, як \you\should\never\do\thatу рядку з подвійним цитуванням, а не одноцитуваним рядком, призведе до нових рядків, вкладок та катастрофи.)


Так, хтось подумав про кращий спосіб зробити це, але PHP наполягає на тому, що кожен оператор повинен бути іншим. Мені цікаво, у чому тут питання зловживання.
Алан Пірс

Погодьтеся. Для PHP потрібні простори імен, але цей синтаксис
накрутить

9

Я зневажаю той факт, що фігурні дужки можуть бути необов’язковими після заяви if / while / for.

Особливо, коли я бачу такий код,

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

Будь ласка, просто вставте брекети і виконайте це.


6
Хм .. це залежить. Для "Abort Ifs", який просто перевіряє стан і повертає код помилки (або кидає виняток), я швидше не побачив дужки.
Біллі ONeal

4
Я погодився б, якби ви обмежили себе крайніми багаторівневими справами, але ваше твердження занадто просте. Існує велика корисність у можливості мати короткі форми для простих одноразових ifs і циклів.
Тімві

2
Моє правило: лише якщо заява вимагає декількох субстатей або якщо воно містить таке твердження, воно повинно бути загорнуте в дужки. Таким чином for (...) while (...) if (...) { x(); y(); }, краще переписати, як for (...) { while (...) { if (...) { x(); y(); } } }, звичайно, з відповідним відступом.
Джон Перді

6
Я радше навпаки - я зневажаю людей, які наполягають на введенні брекетів, коли вони зовсім непотрібні. Просто навчіться програмувати.
Джеррі Труну

3
Мені дуже подобаються дужки навіть в одиничних, якщо твердженнях. Це змушує мене краще слідкувати за потоком програми.
Рікардо Сантос

9

VBScript не має логічних операторів

На відміну від майже кожної розумної мови, VBScript використовує побітові оператори замість логічних операторів. Що це означає на практиці? Ну, як зазначає Ерік Ліпперт :

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

і

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

НЕ однакові у VBScript!

Ще гірше, однак, це означає, що в VBScript немає короткого замикання на замикання, щоб наступне твердження зірвало вашу програму, якщо BlahєNothing

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

Правильно, VBScript оцінить обидві частини порівняння І, навіть якщо перша - хибна! Просто дозвольте тої раковині ...


3
До дня, коли ви полювали на помилку всередині If x Then ... If Not x Then ... End If ... End Ifта не зрозуміли, що х 2, ви насправді не програмували в VB / VBScript.
конфігуратор

7

EDIT: Після обговорення в коментарях я вирішив оновити цю відповідь, щоб пояснити себе краще.

Я дуже ненавиджу те, як виглядають покажчики функцій у C. Зазвичай будь-яке оголошення змінної виглядає як кортеж: type varname; Декларації вказівника функції з іншого боку виглядають як оголошення функції з * перед назвою функції. Я можу прийняти це як опис типу вказівника, але в C це оголошується і тип, і ім'я змінної цього типу. Для мене це виглядає непослідовно, оскільки декларації типу інакше відрізняються від декларацій змінних. struct myStruct{int X; int Y;}визначає лише тип, він не визначає названу змінну myStruct. Так само я не бачу причин декларування типів та оголошень змінних об'єднуватись в одне атомне твердження у функціональних покажчиках, і не оцінюю відхилення відtype varname; структури.

Хтось зазначав, що це відповідає деякому спіральному правилу, і це може бути так, але ознака хорошого синтаксису полягає в тому, що він сам пояснює, і його внутрішня логіка очевидна. Правило спіралі ні в якому разі не очевидно.


1
Це відповідає решті мови, тож, можливо, ваш захват стосується синтаксису деклараторів C взагалі? Ви віддаєте перевагу синтаксис, який використовується в Go ?
finnw

Послідовно, яким чином? Зазвичай йдеться: введіть varname; І коли ми створюємо новий складений тип, як структура, спочатку надходить декларація, можливо, з typedef, а потім ми створюємо змінну цього типу. Коли ми оголошуємо покажчик функції, це int (* foo) (int arg1, int arg2), який потім використовується як тип аргументу, переданого функції: void newFoo (int (* foo) (int arg1, int art2 )) .... і як змінна: foo = a_compatible_func; Я думаю, що спочатку оголошення функції, а потім наступне оголошення var буде більш послідовним, як-от так: typedef int (* foo) (int, int) MyFoo; MyFoo myfoo;
EpsilonVector

Ось чому ви отримали typedef.
zneak

4
@EpsilonVector: Я схильний погоджуватися, що синтаксис покажчика функції неприємний, але слід дотримуватися простого правила, яке полегшує читання. Правило спіралі за годинниковою стрілкою (можливо, ви це бачили?): C-faq.com/decl/spiral.anderson.html
greyfade

1
EpsilonVector: Я не впевнений, що ви очікуєте від декларації змінної вказівника для оголошення, окрім імені змінної.

6

Точки з комою у VBScript - або їх відсутність

Я весь день працюю мовами, які очікують крапки з комою в кінці кожного рядка. Додайте його до кінця рядка у VBScript і ваш код більше не працює.


4
голосування вгору, не тому, що мені особливо подобаються крапки з комою, а тому, що я дуже ненавиджу те, як VB заохочує дійсно довгі рядки , роблячи такі перебої таким незручним.
Shog9

6

Аргументи вводу / виводу. Я все за аргументи (добре, що я є), аргументи теж чудові, але аргумент, який повинен передати ці два стани, мене знущає.

Я націлююсь тут на функції, які беруть вхід з параметра, а потім замінюють цей вхід деяким результатом. Добре передавати об’єкт за посиланням, щоб оновити його. Але, в основному, для примітивних типів, беручи предмет, використовують його, а потім змінюють його повністю, мені не підходить. Не слід змінювати значення аргументу через вхід.


Яку мову ви маєте на увазі? Якщо C #, то я не погоджуюся з тим, що це дратує, тому що це завжди явно (на відміну від C ++.) Також я не знаю жодної основної мови, де ваші змушені оголошувати аргументи як вхід / вихід.
finnw

@finnw Я ніколи не бачив мови, де вам доводилося говорити і inдля inаргументів, я просто про них говорю. Також, на мою думку, ніщо не може виправдати аргумент про введення / виведення, а їх явне вираження не знімає біль. Не повинно бути причин ініціалізувати локальну змінну зі значенням, корисним для функції, і мати цю саму змінну, а потім раптом містити все, що функція вирішила туди поставити. Ці два мають бути різними. Завжди.
zneak

Вибачте, я там був не дуже зрозумілий. Я мав на увазі сказати: "Я не знаю жодної мови, де всі аргументи неявно вставлені в + вихід", тобто ви не змушені використовувати цю функцію, але є законні випадки використання (наприклад, оновлення, structколи нове значення залежить від значення іншого поля того ж struct.)
finnw

@finnw Об'єкти, передані посиланням (як екземпляри classоб'єктів у C #), змінені функцією, мені добре. Крім , що я не люблю неконстантие структури, пропускання structз refключовим словом , щоб оновити це добре, теж. Те, що я насправді ненавиджу, це коли введення перезаписується результатом. Найкращий приклад, який я можу придумати, - це acceptфункція сокета Berkeley : для цього потрібен socklen_t*аргумент, який на вводі повинен містити розмір struct sockaddr*переданого вами; і на виході буде містити кількість байтів, які були записані до нього. Це має бути злочинним.
zneak

Я погоджуюся, що це погано (IIRC деякі функції вводу / виводу Win32 роблять те саме), але це неправильне використання функції (виклик функції змінює значення передаваної змінної, а не лише її значення), і це не означає функцію сама по собі погана.
finnw

6

Оголошення масиву в C і C ++.

Як правило, змінна декларація має формат type variable_name. Ви можете легко читати ці декларації зліва направо. Але int foo[size]спочатку виглядає, що він оголошується fooяк int, а потім читаєш далі і бачиш, що foo's типу "масив цілих чисел". int[size] fooчитається набагато краще.

І я ненавиджу, коли програмісти оголошувати покажчики , як це з тієї ж причини: int *foo. Я чомусь не зрозумів, що це типовий спосіб написання.


1
Повторні декларації вказівника: вони написані так, тому що ' ' пов'язується з ім'ям змінної, а не з типом. Так int* a, b;само * не декларується aі bяк покажчики; тільки aє. Отже, краще записати це як int *a, b;(або ще краще записати їх як дві декларації).
Стів Мельников

Влучне зауваження. Це занадто погано *, не прив'язується до типу.
Яків

2
І це не означає нічого про функціональні вказівники ... void(int) *f;? Ні:void (*f)(int);
Зауважте, що потрібно самостійно - придумайте ім'я

У сучасному C ++ дуже мало потреби в покажчиках та масивах.
fredoverflow

2
@Steve Melnikoff: Хоча я поставив +1 цій відповіді, я вважаю, що int* a, b;питання, про яке ви згадали, набагато більш кричуще.
j_random_hacker

5

Надмірна параметризація на Java:

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

Яку ще параметризацію типу, на думку компілятора, fooможе мати?


4
Я сподіваюся, що вам відомо про обмеження типу Java (обмежений)? HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
finnw

1
Ява 7:HashMap<String,HashMap<String,String>> foo = new HashMap<>();
Барт ван Хекелом

5
Ну, це може бути будь-який тип, який він хоче, типи все одно стираються ...
конфігуратор

Ти маєш на увазі відсутність типового умовиводу?
зниклий фактор

What other type parameterization does the compiler think foo could have?- З якої б то не було причини сирого типу - так, як якщо б хто-небудь розумний навіть змішав би необроблені та параметризовані типи.
maaartinus

5

Оскільки люди вже скаржилися на =vs. ==, дозвольте мені зазначити набагато гіршу альтернативу. PL / У мене було :=і те =, і коли щось було "очевидно" завданням, це дозволило б вам піти з використання =. Використання :=дозволяє змусити щось бути завданням у ситуації, коли компілятор інакше трактує це як порівняння.

На жаль, компілятор не завжди вирішував такі речі, як ви могли очікувати. Розглянемо лише один очевидний приклад:

A = B = 0;

Тепер для більшості людей, знайомих з більшістю "звичайних" мов, сенс цього досить очевидний - присвоїти 0 як A, так і B. PL / I - трохи трохи ... хоча все. З причин, відомих лише (божевільним) дизайнерам мови, перша =інтерпретується як завдання, а друга =інтерпретується як порівняння. Отже, це порівнює B з 0, а потім присвоює результат цього порівняння A (дотримуючись конвенції у стилі С, що "false" призводить до 0, а "true" у 1).

Отже, якщо B було 0, то A стає 1. Інакше, A стає 0. Іншими словами, замість того, щоб призначати те саме значення A і B, це фактично гарантує, що A не може мати те саме значення, що і B.

Підсумок: хоча стиль C / C ++ / PHP спочатку здається болем, альтернатива набагато гірша 1 .

1 Ну, технічно, є й інша альтернатива: стиль Паскаль, де =завжди потрібно порівняння та призначення :=. Використовуючи це деякий час, досить очевидно (принаймні, для мене), що завдання є більш поширеним, ніж порівняння, що якщо ви збираєтеся вимагати додаткові "речі" для роз'єднання цих двох, ви обов'язково повинні зберігати завдання чистими та простими і вимагають додаткового «гранжу» на порівняннях, а не навпаки.


1
Я б навіть запропонував використовувати ==для рівності та :=для призначення. Таким чином у вас є більше набрати, але уникнути самотніх =допомагає уникнути помилок.
maaartinus

@maartinus: принаймні для мене, це звучить як абсолютна найгірша можливість, але таке життя ...
Джеррі Коффін

3

Perl

  1. Я б хотів, щоб Перл дозволив мені написати if($x < 10) do_something();. На даний момент ви повинні написати це як do_something() if($x < 10);або як if($x < 10) { do_something(); }.

9
do_something() if ($x < 10);не так вже й погано
zneak

Це не так, і в багатьох випадках набагато чистіше, ніж if(..) ...завантажувати, оскільки ви можете отримати всі вирази для вирівнювання праворуч. Але є випадки, які мені дуже хочеться сказати if($x < 10) do_something();, і прикро, що Perl мені цього не дозволить.
Гаурав

7
Прикро, поки не пишеш, if ($x<10) do_something(); and_call_me(); а потім дивуєшся, чому ти ніколи не телефонуєш. Я хотів би, щоб C та сім'я вимагали дужок, щоб запобігти подібному типу помилок.
AShelly

2
@AShelly: або чому ти завжди дзвониш насправді.
zneak

1
@zneak За винятком жодних elses. (Я б хотів, щоб це було EXPR1 if COND else EXPR2як у Python)
Ming-Tang,

3

reinterpret_cast<unsigned long>в c ++. Ця операція є корисною для роботи з іноземними API та забезпеченням чисельної точності, чому слід надати такий біль і так некрасиво дивитися?


17
Неприємно нагадувати вам, що ви повинні прагнути писати код, який цього не вимагає. :)
greyfade

Для мене це хороший теоретичний різновид аргументації з інформатики, але, на моєму досвіді, це надто корисно уникати (Однак, багато мого досвіду - це звичайний C, тому я, мабуть, маю упередженість).
AShelly

5
Це насправді не теоретичний аргумент CS: Використання reinterpret_castв C ++ - дуже сильний запах коду. У 99% випадків, коли ви збираєтесь ним скористатися, швидше за все, вам не потрібно - ви, мабуть, зробили щось не так. Інші 1% часу ви взаємодієте з C. reinterpret_castпорушує систему типу, щоб змусити щось працювати, коли інакше не може. Зазвичай це погана річ.
greyfade

3

Конструкція for ... у JavaScript та конструкція foreach у PHP під час перегляду масивів. Обидва вони полегшують запис помилок, ніж правильний код.


3
Нічого собі, це таке фігня. "Ніж правильний код". Йди геть.
Джонатан Стерлінг

Якщо мені доведеться написати додатковий код, щоб безпечно їх використовувати, у моїй книзі їх простіше використовувати неправильно. Для ... в потрібні додаткові перевірки, щоб переконатися, що ви не повторюєте об'єкти з прототипу, а foreach вимагає після цього очистити посилання або ризикувати перезаписати останнє значення в масиві.
Joeri Sebrechts

foreach із зміною посилань (& operator) - знаменита помилка ...
umlcat

1
Я розгублений, я думав, що загальновідомо, що конструкція "for..in" у JavaScript зламана ... чому це образливо?
lvilnis

2

Покажчики масивів або масивів покажчиків у C / C ++. Я до цих пір збентежений.


3
Прочитайте тип назад. int[]*є вказівником на масив цілих чисел і int*[]є масивом покажчиків на цілі числа. Добре працює і з consts: int* constє постійним вказівником на цілі числа, тоді як const int*і int const*є вказівниками на постійні цілі числа (або на цілі константи).
zneak

@zneak: "Праворуч ліворуч" не працює, див. згадане правило "спіраль за годинниковою стрілкою" / "всередину" .

Або просто використовуйте typedefs і в цьому немає плутанини.
Біллі ONeal

У сучасному C ++ дуже мало потреби в покажчиках та масивах.
fredoverflow

4
@tchrist: Неправда. int (*p)[10];оголошує pвказівником на масив 10 ints. Якщо sizeof (int) == 4, то p++просунетесь pна 40.
j_random_hacker


1

Javascript / Java тощо, дорівнює порівнянню, наприклад, якщо (a == 1)

Скільки разів я пишу, якщо (a = 1)?

Як людина я це чудово читав. Але перекрутник / компілятор каже: "Ей, я призначу 1 до a, тоді перевірте, чи a дорівнює 1, і чи повірите ви, так, так!"

Підводить мене до стіни.

якщо (a == 1) набагато менш читабельний, і перекладач / упорядник повинен знати, що я маю на увазі; багато інших менших мов (VB) успішно розробляють його протягом сотень років.


Що if (a = true)має означати?
Том Хотін - тайклін

2
Призначення просто не повинно повертати значення. Іноді це корисно, але в більшості випадків це просто біль у шиї.
конфігуратор

у Javascript JSLint знайде цей для вас.
Захарій К

Біда в тому, що призначення в умовах може бути корисним. Я знаходжу <tt> while (element = list-> next ()) </tt> досить розбірливим. Тож я не впевнений, що хотів би її зняти.
Інка

3
@Tom: Це означає, що ти не розумієш булів. Якщо ви мали на увазі if (a == true), просто напишіть if (a). Якщо ви мали на увазі a = true, то ifтвердження є зайвим.
дан04,


0

structPointer->memberв C / C ++. Може бути корисним для читання чужого коду, але мені це не подобається. Два символи замість одного ... яка марна трата місця!


2
На жаль, його слід відрізняти від того ., що стосується членів об'єкта, що не вказує. Неоднозначний синтаксис поганий, мммкай?
greyfade

2
@greyfade: Так! Оскільки компілятор не може використовувати свої системні правила типу, щоб вказати, коли ви використовуєте тип вказівника на структуру, і застосувати дереференцію неявно. Ні, це божевільна розмова! (І все ж воно все ще може якось дати вам повідомлення про помилку, коли ви помилитесь.) У синтаксисі немає нічого неоднозначного. Це просто C - це безлад, як завжди. Delphi робить неявні дереференції просто чудовими, якщо ви насправді працюєте в темних куточках, для яких потрібні вказівники для запису, тому це, безумовно, можна зробити, не плутаючи парсер ...
Мейсон Уілер

5
@Mason: Що стосується таких випадків shared_ptr, коли ->доступ до вмісту, що міститься, та .доступ до властивостейshared_ptr себе? Вибачте, але я тут абсолютно не згоден.
Біллі ONeal

2
може бути і гірше. Може бути PHP, де вам доведеться використовувати ->для доступу членів будь-що .
Карсон Майєрс

1
@maaartinus: Я буду писати будь-який код, який сильно покладається на неочевидний порядок операцій.
Біллі ONeal

0

Багаторядковий код Scala в дужках

Наприклад:

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

Те, що ви насправді отримуєте від цього, є приголомшливим. Він генерує для вас конструктор та геттери та сетери. Але це, безумовно, некрасиво і розбиває всі мої ментальні моделі того, як відрізати код і в основному залишає мені відчуття, ніби я перебуваю в своєрідному химерному сендвічі з Java з одного боку та Ліспом з іншого. (О, зачекайте ... це скоріше сенс Скали.)


Я розгублений - ти маєш на увазі порцію в дужках ( val barі так далі) або частину в фігурних дужках (частина, що йде далі extends Model)? (У цьому коді немає дужок)
Billy ONeal,

3
Частина в дужках. Я англієць. Ми називаємо їх дужками, чорт забирай, тому що в цій ситуації вони не виконують батьківської ролі.
Том Морріс

2
Це виглядає не так вже й погано, якщо відступити таким чином: pastebin.com/h9qC8XGg
missingfaktor

Мені здається більш читаним писати ці списки параметрів конструктора горизонтально, особливо коли у мене є лише кілька параметрів.
MJP

Мені це схоже на метод. Як Симула. Гарна стара школа.
Том Хотін - тайклін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.