Какой синтаксический элемент вы больше всего ненавидите в языке программирования, который вы часто используете? [закрыто]


27

Независимо от того, насколько вы любите язык программирования, в нем всегда есть несколько деталей, которые не так хороши, как могли бы быть.

В этом вопросе я бы хотел особо остановиться на элементах синтаксиса. В языке программирования, который вы часто используете (возможно, ваш любимый язык программирования или, возможно, тот, который вы вынуждены использовать на работе), какой элемент синтаксиса вы считаете наиболее нечитаемым, неясным, неудобным или неприятным?


@ Натан Тейлор, не для этого вопроса, а для другого вопроса .
Finnw

Этот вопрос изменился? Потому что, когда я ответил, он не был сосредоточен на «элементах синтаксиса» ... Мне придется изменить свой ответ сейчас.
Талви Ватиа

@ Талви: Нет, речь шла о синтаксисе с самого начала.
Тимви

@Timwi странно, это должен быть случай «ответить на вопрос, думая, что это был другой вопрос».
Талви Ватиа

Если вы можете голосовать и считаете, что это полезный вопрос или у него есть полезные ответы ниже, пожалуйста, проголосуйте. Сайты 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

2
JavaScript: самый неправильно
понятый в мире

Да, многие ожидают, что JavaScript будет «языком свободной формы», но это не так.
Андреас Рейбранд

13
Это имеет смысл, как только вы поймете, что JavaScript был разработан для создания HTML, который также имеет долгую историю попыток интерпретировать, что ваш код «действительно означает», когда он не синтаксически допустим. (Когда-нибудь посмотрите принцип надежности - самое большое бедствие в истории вычислительной техники.)
Мейсон Уилер,

7
Эти типы ошибок, для меня, являются запахом кода, что программист небрежен и никогда не работал с большинством формальных «строгих» языков, которые обычно вызывают синтаксическую ошибку для пропуска точки с запятой.
Талви Ватиа

7
Wohoo, наконец, кто-то еще, кто также думает, что Принцип Надежности - это катастрофа, которая сделала HTML полным беспорядком.
Роман Старков

39

Синтаксис Java-бина из-за отсутствия свойств 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 выходит из-под контроля, он все еще многословен, он все еще загромождает Javadoc и т. Д.
TheLQ

11
Если вам нужны геттеры для всего, значит что-то не так с клиентским кодом.
Finnw

7
Наличие геттеров и сеттеров нарушает инкапсуляцию. Поле также может быть public. Члены должны быть частными и должны разумно обрабатываться классом с логикой более высокого уровня, а не с получателями и установщиками из клиентского кода.
Greyfade

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

3
@SHiNKiROU: Java выглядит чисто? Я никогда не слышал этого раньше! Моя главная проблема с Java в том, что, казалось бы, простая вещь занимает десятки строк кода, которые я должен мысленно игнорировать.
конфигуратор

33

Чувствительность к пробелам.

Python раздражает меня в этом отношении. Я имею в виду, я отступ правильно так или иначе, но это ошибка мне , что я должен иметь к. Создание представления частью синтаксиса раздражает меня.


8
Вы научитесь любить это
user10008

2
Синтаксис является презентация
Winston Эверт

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/ elsechain, что хорошо, так как семантически похоже. По крайней мере, в C # это все равно не будет тем же, потому что в switchутверждении порядок меток регистра не имеет значения, но в if/ elseэто имеет значение.


1
К сожалению, ваш улучшенный синтаксис избавляет от того, что, возможно, является самой большой особенностью коммутатора в большинстве этих языков: сквозной. «Устройство Даффа» в Си - прекрасный пример ценности этой конкретной «ошибки». В C-подобных языках также распространено использование провала в интерпретаторах и подобных программах.
Greyfade

7
Нет, это не покончит с этим. Требуется только сделать его более явным (используя a 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

Я думаю, что все языки Бейсик делают это ... Я знаю, что оригинал Бейсик и QBasic делают.
Майкл К

OMG, это действительно ужасно .... +1
Микера

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 будет рассматриваться как объектный код.
Том Хотин - tackline

// отлично работает, чтобы закомментировать 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. Серьезно, ВТФ? oO Непротиворечивость Imho является допустимой проблемой для любого API, и просто ответ «использовать достойную IDE» просто не является верным ответом. По крайней мере, разработчики могли бы сформулировать это менее подстрекательски.
Baelnorn

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

19

питон

self параметр в определениях метода экземпляра


В методе класса его обычно называют cls, а использование self противоречит соглашению.

Это действительно имеет смысл, если вы думаете об этом. Это то же самое, что объявить закрытый метод в других языках, параметр self явно указан в python, где он неявен в других языках. Если вы хотите, чтобы он был неявным, добавьте декоратор @classmethod перед объявлением метода. См. Docs.python.org/library/functions.html#classmethod . Изучение деталей того, как это работает, даст вам некоторое представление о том, как это неявно делается на других языках.
Эван Плейс

4
Я понимаю причины и почему это там осталось neopythonic.blogspot.com/2008/10/… но мне все еще не нравится
Горан Перош

@Evan Plaice: «Параметр self явно указан в python, где он неявен в других языках». Это только одна часть истории. Другая часть - это python, который печатается еженедельно. Вместе это ужасно, забывать selfбывает легко и стоит времени.
Maaartinus

@maaartinus Затем добавьте декоратор метода класса к вашим методам экземпляра. Не имеет ничего общего со «слабо напечатанным». Это просто делает связь между статическими методами / функциями (без параметра «self») и методами экземпляра (включая «self») очевидными. Метод экземпляра не знает о своем родительском классе, если вы не дадите ему ссылку для этого. В других языках отличительная черта, которую я обозначил, скрыта за синтаксическим сахаром. Если бы у меня был выбор сделать все заново, я бы сначала начал изучать ООП на Python.
Эван Плейс

18

Джава

Период. Полная остановка. Конец истории.

Когда начать? О, я знаю, с чего начать: Java - безумно сложный, уродливый, глупый и по своей сути сломанный дженерик. Нужно ли мне сказать больше? :( Хорошо, хорошо, тогда: erasure .

Тогда есть недетерминированное управление ресурсами. Kewl Footcher!

Что дальше? Ах да: глупые регулярные выражения Java - моя самая раздражающая, кипящая говядина. Я не могу сосчитать, сколько раз меня держали в руке из-за недостатка обратной косой черты. Это даже хуже, чем отсутствие доступа к каким-либо свойствам Юникода в этом тысячелетии, что вполне закономерно. Десять офигенных лет устарели !!! Совершенно бесполезно. Мусор это.

Тогда есть ошибка, что ярлыки класса персонажа не работают на не-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: вы просто захотите разбить вещи, все это так больно и сломано. Я не могу поверить, что люди терпят это. Некоторые нет .

Тогда мы можем начать говорить об идиотской бессмыслице 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 , и, конечно, вы не получите никакого предупреждения, что вы не можете этого сделать. Это просто делает неправильную вещь.

Stoooopid.

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

Riiiiiiiight!

Знаете ли вы, что в Java нет способа сделать isatty(0)звонок? Тебе даже не позволено думать такие мысли. Это не будет хорошо для вас.

И затем есть вся мерзость пути класса.

Или тот факт, что невозможно указать кодировку исходного файла Java в том же исходном файле, чтобы вы не потеряли его? Я еще раз требую знать: ЧТО, ЧТО ОНИ МЫ ДУМАЛИ?

Останови безумие! Я не могу поверить, что люди терпят этот мусор. Это полная шутка. Я бы предпочел быть приветствующим Walmart, чем страдать от слингов и стрел возмутительного безумия на Яве. Это все сломано, и они не только не могут это исправить, но и не могут это исправить.

Это те же самые люди-лисички, которые гордились тем, что сделали незаконным printf()функционирование. Ну и дела, что действительно сработало очень хорошо, не так ли?

Чистые черепа. Шлепки слишком добры к ним. Если бы я хотел программировать на ассемблере, я бы. Это не подлежащий спасению язык. У императора нет одежды.

Мы ненавидим это. Мы ненавидим это навсегда . Пусть умирает, умирает, умирает !


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

4
-1. За исключением комментариев к регулярному выражению и экранирования Unicode, ни одна из упомянутых вами вещей не является элементом синтаксиса.
Йорг Миттаг

3
@ Йорг, хочешь синтаксис? Хорошо, хорошо: Java позволяет вам помещать управляющие символы, включая ESC и NUL, в идентификаторы. Что они думают ???
2010 года

4
@tchrist: Ух ты! Если я когда-нибудь снова напишу программу на Java, все мои переменные будут иметь имена, состоящие из различного числа символов ^H
возврата

1
@ tchrist, тебе лучше?

16

Синтаксис объявления указателя функции в C и C ++:

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

Это объявляет указатель на функцию с именем, fчье pointee может принимать два ints и возвращать int.

Я бы предпочел такой синтаксис:

f: (int, int) => int

Скажем, вы хотите объявить указатель на функцию, gчей pointee может взять два ints и функцию из intи intв int, и вернуть 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 ++, синтаксис которых даже хуже, чем на обычных указателях функций)
Тамас Селеи,

14

Многословие в Java.

то есть:

public static final int 

6
В сравнении с? (15 символов)
TheLQ

7
По сравнению с: const intнапример.
ОскарРиз

11
"public static final int x = 4;" по сравнению с "х = 4" в Haskell.
Джаред Апдайк

24
Это не многословие. Попробуйте написать, a+(b*c)/d*e+f/g^20используя BigIntegerв Java. Почему этот язык не допускает перегрузки операторов?
МАК

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

12

\ we \ notnt \ fix \ синтаксис пространства имен нашего \ parser в PHP

Синтаксис не только уродлив, он приводит к путанице, когда новым разработчикам приходится задумываться о пространствах имен в строках. (PHP интерполирует обратные слэши в строках в двойных кавычках в качестве escape-последовательностей. Попытка представить пространство имен, как \you\should\never\do\thatв строке в двойных кавычках, а не в строке в одинарных кавычках, приведет к появлению новых строк, вкладок и к катастрофе.)


Да, кто-то придумал лучший способ сделать это, но PHP настаивает на том, что каждый оператор должен быть разным. Мне любопытно, что проблема злоупотребления здесь.
Алан Пирс

Согласен. PHP требует пространства имен, но этот синтаксис
облажался

9

Я презираю тот факт, что фигурные скобки могут быть необязательными после оператора if / while / for.

Особенно, когда я вижу код, как,

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

Пожалуйста, просто вставьте скобки и покончите с этим.


6
Хм .. это зависит. Для «Прервать Ifs», которые просто проверяют условие и возвращают код ошибки (или выдают исключение), я бы предпочел не видеть скобки.
Билли Онил

4
Я бы согласился, если бы вы ограничились крайними многоуровневыми случаями, но ваше утверждение слишком поверхностно. Существует возможность использовать короткие формы для простых операторов if и циклов с одним оператором.
Тимви

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

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

3
Мне действительно нравятся квадратные скобки даже в одиночных операторах if. Это заставляет меня лучше следить за ходом программы.
Рикардо Сантос

9

VBScript не имеет логических операторов

В отличие от почти каждого разумного языка, VBScript использует побитовые операторы вместо логических операторов. Что это значит на практике? Ну, как отмечает Эрик Липперт :

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

а также

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

НЕ одинаковы в VBScript!

Еще хуже, хотя, это означает , что нет никакой оценки короткого замыкания в VBScript , так что следующий оператор будет врезаться вашей программой , если BlahISNothing

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

Правильно, VBScript оценит обе части сравнения AND, даже если первая из них неверна! Просто позволь этому погрузиться ...


3
До того дня, когда вы обнаружили ошибку внутри If x Then ... If Not x Then ... End If ... End Ifи выяснили, что x равен 2, вы на самом деле не программировали на VB / VBScript.
конфигуратор

7

РЕДАКТИРОВАТЬ: После обсуждения в комментариях я решил обновить этот ответ, чтобы объяснить себя лучше.

Я действительно ненавижу то, как указатели на функции выглядят в C. Обычно любое объявление переменной выглядит как кортеж: type varname; Объявления указателя функции, с другой стороны, выглядят как объявление функции с * перед именем функции. Я могу принять это как описание типа указателя, но в Си это объявляет как тип, так и имя переменной этого типа. Это выглядит противоречивым для меня, потому что объявления типов иначе отличаются от объявлений переменных. struct myStruct{int X; int Y;}определяет только тип, но не определяет переменную с именем myStruct. Точно так же я не вижу причин для объединения объявлений типов и объявлений переменных в один атомарный оператор в указателях функций, а также я не ценю отклонение отtype varname; структуры.

Кто-то указал, что это согласуется с каким-то спиральным правилом, и это может иметь место, но признаком хорошего синтаксиса является то, что он говорит само за себя, а его внутренняя логика очевидна. Спиральное правило не очевидно ни в коем случае.


1
Это согласуется с остальным языком, так что, может быть, ваше мнение касается синтаксиса C-объявлений вообще? Вы предпочитаете синтаксис, используемый в Go ?
Финн

В каком смысле? Обычно это идет: тип 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

Аргументы в / из. Я весь в аргументах (хорошо, что я есть), наши аргументы тоже хороши, но аргумент, который должен передать эти два состояния, бесит меня.

Здесь я нацеливаюсь на функции, которые берут входные данные из параметра, а затем перезаписывают этот вход некоторым выводом. Это нормально, чтобы передать объект по ссылке, чтобы обновить его. Но, в основном, для примитивных типов: взять объект, использовать его, а затем полностью его изменить, я не прав. Вы не должны менять значение аргумента через inout.


Какой язык ты имеешь в виду? Если C #, то я бы не согласился, что это раздражает, потому что это всегда явно (в отличие от C ++.) Также я не знаю ни одного основного языка, где вы вынуждены объявлять аргументы как in / out.
Финн

@finnw Я никогда не видел языка, на котором ты должен был говорить inза inаргументы, я просто говорю о них. Кроме того, по моему мнению, ничто не может оправдать аргументы in / out, и их явное выражение не снимает боль. Не должно быть никаких причин для инициализации локальной переменной значением, полезным для функции, и иметь эту же переменную, которая затем внезапно будет содержать все, что функция решила поместить туда. Эти два должны быть разными. Всегда.
zneak

Извините, мне было не очень ясно. Я имел в виду сказать: «Я не знаю ни одного языка, где все аргументы неявно вводятся +», т. Е. Вы не обязаны использовать эту функцию, но существуют законные варианты использования (например, обновление, structгде новое значение зависит от значения другого поля того же struct.)
finnw

@finnw Объекты, переданные по ссылке (например, экземпляры classобъектов в C #), модифицируемые функцией, подходят мне. Кроме того, что мне не нравятся непостоянные структуры, передача structс refключевым словом для его обновления тоже подойдет. Что я действительно ненавижу, так это когда ввод перезаписывается выводом. Лучший пример, который я могу вспомнить, - это acceptфункция сокета Беркли : ей нужен socklen_t*аргумент, который при вводе должен содержать размер struct sockaddr*передаваемого вами значения; и на выходе будет содержать количество байтов, которые были записаны в него. Это должно быть преступным.
zneak

Я согласен, что это плохо (IIRC некоторые функции ввода-вывода Win32 делают то же самое), но это неправильное использование функции (вызов функции изменяет значение передаваемой переменной, а не только ее значение), и это не означает функцию само по себе плохо.
Финн

6

Объявления массивов в C и C ++.

Как правило, объявление переменной имеет формат type variable_name. Вы можете легко прочитать эти объявления слева направо. Но int foo[size]сначала выглядит так, будто оно объявляется fooкак int, а затем вы читаете дальше и видите, что foo типа «массив целых чисел». 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
@ Стив Мельникофф: Хотя я добавил +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

Поскольку люди уже жаловались на « =против» ==, позвольте мне указать на гораздо худшую альтернативу. У PL / I было и то :=и другое =, но когда что-то было «очевидно» заданием, это позволяло бы вам избежать использования =для этого. С помощью:= позволяет вам заставить что-то быть присваиванием в ситуации, когда компилятор иначе интерпретирует это как сравнение.

К сожалению, компилятор не всегда принимал решения так, как вы ожидаете. Рассмотрим только один очевидный пример:

A = B = 0;

Теперь, для большинства людей, знакомых с большинством "обычных" языков, смысл этого довольно очевиден - присваивать 0 как A, так и B. PL / I немного ... отличается. По причинам, известным только (безумным) разработчикам языка, первое =интерпретируется как задание, а второе= - как сравнение. Следовательно, это сравнивает B с 0, а затем присваивает результат этого сравнения A (в соответствии с соглашением в стиле C, что «false» приводит к 0 и «true» в 1).

Итак, если B было 0, то A становится 1. В противном случае A становится 0. Другими словами, вместо того, чтобы присваивать одно и то же значение A и B, это фактически гарантирует, что A не сможет иметь то же значение, что и B.

Итог: хотя изначально стиль C / C ++ / PHP кажется болезненным, альтернатива намного хуже 1 .

1 Технически, есть другая альтернатива: стиль Pascal, где =всегда означает, что всегда требуется сравнение и назначение :=. После того, как вы используете это в течение некоторого времени, становится достаточно очевидным (по крайней мере для меня), что назначение является более распространенным, чем сравнение, что, если вам потребуется дополнительная «вещь» для устранения неоднозначности, вы должны определенно сохранять задания чистыми и простыми, и требует дополнительных «гранж» при сравнении, а не наоборот.


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

@maartinus: по крайней мере для меня, это звучит как наихудшая возможность, но такова жизнь ...
Джерри Гроб

3

Perl

  1. Я хотел бы, чтобы Perl позволил мне написать 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 Кроме как нет else. (Хотелось бы, чтобы это было EXPR1 if COND else EXPR2как у Python)
Ming-Tang

3

reinterpret_cast<unsigned long>в с ++. Эта операция полезна при работе с зарубежными API и обеспечивает точность числовых данных. Почему печатать так трудно и так уродливо?


17
Ужасно напоминать вам, что вы должны стремиться писать код, который не требует этого. :)
Greyfade

Для меня это хороший теоретический аргумент в области компьютерных наук, но, по моему опыту, его слишком полезно избегать (однако, большая часть моего опыта - простой старый C, поэтому у меня, вероятно, предвзятость).
AShelly

5
Это не совсем теоретический аргумент CS: использование reinterpret_castв C ++ - очень сильный запах кода. В 99% случаев, когда вы собираетесь его использовать, скорее всего, вам это не нужно - вы, вероятно, сделали что-то не так. Остальные 1% времени, когда вы взаимодействуете с C., reinterpret_castломает систему типов, чтобы заставить что-то работать, когда это иначе не может. Обычно это плохо.
Greyfade

3

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


3
Вау, это такая фигня. «Чем правильный код». Уходи.
Джонатан Стерлинг

Если мне нужно написать дополнительный код для безопасного их использования, их проще использовать неправильно в моей книге. For ... in требует дополнительных проверок, чтобы убедиться, что вы не выполняете итерации по объектам из прототипа, а foreach требует, чтобы вы впоследствии очистили ссылки или рискнули перезаписать последнее значение в массиве.
Джори Себрехтс

foreach с изменяющимися ссылками (& operator) - это известная ошибка ...
umlcat

1
Я в замешательстве, я думал, что всем известно, что конструкция "for..in" в javascript нарушена ... почему это оскорбительно?
lvilnis

2

Указатели массивов или массивов указателей в C / C ++. Я все еще смущен этим.


3
Читайте тип в обратном порядке. int[]*это указатель на массив целых чисел и int*[]массив указателей на целые числа. Хорошо работает и с consts: int* constэто постоянный указатель на целые числа, тогда как const int*и int const*являются указателями на постоянные целые числа (или на целочисленные константы).
zneak

@zneak: «Справа налево» не работает, см. упомянутое правило «спираль по часовой стрелке» / «наизнанку» .

Или просто используйте typedefs и нет путаницы.
Билли Онил

В современном C ++ очень мало потребности в указателях и массивах.
fredoverflow

4
@tchrist: не правда. int (*p)[10];объявляется pкак указатель на массив из 10-ти. Если 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)должно означать?
Том Хотин - Tackline

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
@ Мейсон: А как насчет случаев 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 с одной стороны и Lisp с другой. (Ой, подождите ... это скорее точка Скала.)


Я в замешательстве - вы имеете в виду часть в скобках ( val barи так далее) или часть в фигурных скобках (часть после extends Model)? (В этом коде нет скобок)
Billy ONeal,

3
Часть в скобках. Я английский. Мы называем их скобками, черт возьми, потому что в этой ситуации они не играют роль скобок.
Том Моррис

2
Это не выглядит так уж плохо, если отступать таким образом: pastebin.com/h9qC8XGg
missingfaktor

Я нахожу более удобным для чтения эти списки параметров конструктора по горизонтали, особенно когда у меня есть только несколько параметров.
MJP

Похоже, метод для меня. Как и Симула. Старая добрая школа
Том Хотин - tackline
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.