Странная языковая особенность

974

Какая, на ваш взгляд, самая удивительная, странная, странная или действительно "WTF" языковая функция, с которой вы столкнулись?

Пожалуйста, только одна функция в ответе.

Роберт Харви
источник
5
@gablin Я думаю, что если бы вы объединили разделители LISP с регулярным выражением PERL, используя синтаксический анализ javascript, вы бы покрыли 90% WTF ...
Талви Ватиа

Ответы:

1859

В C массивы могут быть проиндексированы следующим образом:

a[10]

что очень распространено.

Тем не менее, менее известная форма (которая действительно работает!):

10[a]

что означает то же самое, что и выше.

Эдан Маор
источник
758
это потому, что [10] означает * (a + 10) ... и 10 [a] означает * (10 + a) :)
Мишель Гокан
77
Не забудьте "Hello World" [я]. Или я ["Hello World"]
Ричард Пеннингтон
167
Или, что более полезно, «0123456789abcdef» [x & 0xf]
Dipstick
17
@frunsi: всегда работает как положено. Добавление указателя - это не то же самое, что простое целочисленное добавление по адресам. Это коммутативно, независимо от того, какой размер является рассматриваемым типом.
Р. Мартиньо Фернандес
12
@mcv - a [10] - это то же самое, что и «* (a + 10)», где выражение «a + 10» является арифметикой указателя (а поскольку a - это короткий, в вашем примере + 10 означает «начало в адрес а, и переместить 10 шорт, то есть 20 байтов). Выражение 10 [a] интерпретируется как «* (10 + a)», где «10 + a» также является арифметикой указателя и обрабатывается точно так же.
Эдан Маор
1292

В JavaScript:

 '5' + 3 gives '53'

В то время как

 '5' - 3 gives 2
Dipstick
источник
81
Я помню, когда я впервые начал использовать javascript, используя такую ​​технику для добавления чисел в строки: «111» - «222» дает 333, тогда как «111» + «222» дает «111222».
Каллум Роджерс
112
+для конкатенации строк ужасно
Маттео Рива
416
+ Конкат не проблема. Слабая типизация есть.
FogleBird
270
@FogleBird Никто на самом деле не проблема. Это просто сочетание двух с противоречивыми правилами принуждения.
ТМ.
70
Так что, в основном, + - это конкат, когда задействована строка. Почему они не могут кодировать что-то вроде «123456» - 456 = «123»? Это было бы интересно.
Джимми Лин
872

В JavaScript следующая конструкция

return
{
    id : 1234,
    title : 'Tony the Pony'
};

returnundefined является синтаксической ошибкой из-за хитрой неявной вставки точек с запятой на новой строке после return. Следующее работает, как вы ожидаете, хотя:

return {
    id : 1234,
    title : 'Tony the Pony'
};

Еще хуже, этот работает также (по крайней мере, в Chrome):

return /*
*/{
    id : 1234,
    title : 'Tony the Pony'
};

Вот вариант той же проблемы, который не приводит к синтаксической ошибке, просто молча терпит неудачу:

return
    2 + 2;
DrJokepu
источник
225
Вставка точки с запятой - одна из самых злых частей JavaScript.
230
Вы всегда сталкиваетесь с проблемами, когда разрабатываете языковые функции, исходя из предположения, что ваши пользователи будут в основном идиотами.
Роб Ван Дам
8
У меня действительно была эта проблема, будучи самим разработчиком на c #, я поставил скобку в новую строку. Мне потребовались часы, чтобы понять, в чем была проблема. Даже когда я решил проблему, я не знал, в чем проблема, пока не прочитал ваш ответ!
Федор Хайду
24
Ник Реталлак: Потому что из-за синтаксиса C-подобных фигурных скобок и точек с запятой в JavaScript, совершенно не очевидно, что переводы строки являются значительными.
Тамас Чинеге
19
Если вы не должны использовать стиль C при программировании на JavaScript, тогда разработчикам языка JavaScript было довольно неправильно выбирать синтаксис в стиле C.
Райан Ланди
795

Таблица истинности JavaScript:

''        ==   '0'           // false
0         ==   ''            // true
0         ==   '0'           // true
false     ==   'false'       // false
false     ==   '0'           // true
false     ==   undefined     // false
false     ==   null          // false
null      ==   undefined     // true
" \t\r\n" ==   0             // true

Источник: Даг Крокфорд

Chandra Patni
источник
237
Хорошо, что в Javascript есть оператор ===.
Аноним
65
Так какая цель ==служит в глазах языкового дизайнера?
Крис С
137
Смущающие люди.
Хавьер
123
Было бы хорошо, если бы ==имел значение ===, а затем был еще один оператор, что-то вроде ~=этого позволяло приведение типов.
ТМ.
18
@Otto На самом деле, так как мы гиков, его пример показывает, что == не является симметричным. На данный момент я не видел, как коммутативность будет указываться для бинарного отношения.
PeterAllenWebb
660

Триграфы в C и C ++.

int main() {
   printf("LOL??!");
}

Это напечатает LOL|, потому что триграф ??!преобразован в |.

Andreas Bonini
источник
71
Быстро! Расскажите всем программистам C / b /!
Эстебан Кюбер
235
Триграфы удивительны, потому что вы можете быть уверены, что никто никогда не узнает, что ??! будет означать от Google, не зная уже имя.
Заратустра
56
Триграфы по умолчанию отключены в GCC.
Састанин
360
Они позволяют использовать «оператор WTF»: (foo ()! = ERROR) ??! ??! cerr << "Произошла ошибка" << endl;
user168715
57
Trigraphs были неизбежным злом, когда они были введены. Некоторые платформы просто не включали определенные символы ключа в язык, так что это были либо «триграфы», либо «у вас не может быть конца-конца-оператора C-компилятора, так что иди используйте ассемблер». Проверьте описание Страуструпа в "Языке программирования C ++".
Евро Мицелли
573

Удовольствие от автоматического бокса и целочисленного кэша в Java:

Integer foo = 1000;
Integer bar = 1000;

foo <= bar; // true
foo >= bar; // true
foo == bar; // false

//However, if the values of foo and bar are between 127 and -128 (inclusive)
//the behaviour changes:

Integer foo = 42;
Integer bar = 42;

foo <= bar; // true
foo >= bar; // true
foo == bar; // true

объяснение

Быстрый взгляд на исходный код Java покажет следующее:

/**
 * Returns a <tt>Integer</tt> instance representing the specified
 * <tt>int</tt> value.
 * If a new <tt>Integer</tt> instance is not required, this method
 * should generally be used in preference to the constructor
 * {@link #Integer(int)}, as this method is likely to yield
 * significantly better space and time performance by caching
 * frequently requested values.
 *
 * @param  i an <code>int</code> value.
 * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    if (i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

Примечание: по IntegerCache.high умолчанию, 127если не установлено свойством.

Что происходит с автобоксом, так это то, что foo и bar одинакового целочисленного объекта извлекаются из кэша, если не созданы явно: например foo = new Integer(42), при сравнении равенства ссылок они будут истинными, а не ложными. Правильный способ сравнения целочисленного значения использует.equals;

yx.
источник
31
Мне потребовалось пару секунд, чтобы понять, почему ... java должен хранить пул экземпляров Integer для значений от -128 до 128, в противном случае он выделяет новое целое число, верно?
Майк Акерс
18
однако имейте в виду, что если вы укажете новое Integer (42), он не будет использовать экземпляр из пула, поэтому foo == bar будет иметь значение false
z -
10
Я всегда использую целые числа вместо целых, если это возможно, но если по какой-то причине мне пришлось использовать целые числа, я должен просто использовать .equals () вместо ==?
MatrixFrog
246
Так рада, что я программист на C #.
87
@Will: C # имеет несколько очень похожих ошибок. См. Blogs.msdn.com/jmstall/archive/2005/03/06/386064.aspx
spookylukey
373

Цитируя Нила Фрейзера (смотрите в конце этой страницы),

try {
    return true;
} finally {
    return false;
}

(в Java, но поведение, очевидно, одинаково в JavaScript и Python). Результат оставлен читателю в качестве упражнения.

РЕДАКТИРОВАНИЕ: Пока мы находимся на предмете, рассмотрите также это:

try {
    throw new AssertionError();
} finally {
    return false;
}
лоренцог
источник
42
+1. По какой-то причине я нахожу это смешным и не могу перестать хихикать.
2010 года
153
К счастью, C # не допускает такого безумия ...Control cannot leave the body of a finally clause
Ричард Эв
64
Это возвращает, ложь, не так ли? Это может выглядеть как WTF (и, возможно, он один), но я живу по правилу: в конце концов всегда побеждает, если только вы раньше не разбили Машину.
Майкл Стум
28
Честно говоря, я виню в том, что TDWTF хорошо объяснил, что помнил, что, в конце концов, всегда выигрывает, если вы не дергаете за шнур питания: thedailywtf.com/Articles/My-Tales.aspx
Майкл
22
Я не уверен, что код должен вернуть в этом случае. Но я абсолютно уверен, что вы не должны ставить returnв finallyпункт.
Jfs
325

APL (кроме ВСЕГО), возможность написать любую программу в одну строку.

например , игра жизни Конвея в одной строке в APL :

альтернативный текст http://catpad.net/michael/APLLife.gif

Если эта строка не WTF, то ничего нет!

А вот и видео

lkessler
источник
19
Я люблю APL. Ах, радости тратить целый день, чтобы написать половину строки кода! Первое, что я сделаю, когда получу клавиатуру, на которой я могу запрограммировать отображаемые буквы, - это заново познакомиться с APL.
Даниэль С. Собрал
24
Похоже на язык для греков.
Эско
45
@Erik: Есть радость в написании кода, который посвящен исключительно тому, что вы хотите, а не тому, как туда добраться. Выражать ваш код в одном выражении. Это как идеальный срез катаны. Конечно, в реальном бою я бы предпочел пистолет.
Даниэль С. Собрал
7
@ Даниель: Вы тратите весь день, чтобы написать строку кода ... и целую неделю, чтобы прочитать строку кода. ;-)
Юрген А. Эрхард
93
APL было бы здорово увидеть в научно-фантастическом боевике. Я могу представить, как кто-то сидит в трехцветном терминале и бормочет: «Измени вектор ракет противника ... Транспонировать ... Пи раз логарифм ... Повышай и выполняй!» с последующими взрывами и аплодисментами.
Джои Адамс
321

Можно использовать странные шаблоны C ++, лучше всего демонстрируемые «Многомерными аналоговыми литералами», которые используют шаблоны для вычисления площади «нарисованных» фигур. Следующий код является допустимым C ++ для прямоугольника 3x3

#include"analogliterals.hpp"
using namespace analog_literals::symbols;

          unsigned int c = ( o-----o
                             |     !
                             !     !
                             !     !
                             o-----o ).area;

Или другой пример с трехмерным кубом:

  assert( ( o-------------o
            |L             \
            | L             \
            |  L             \
            |   o-------------o
            |   !             !
            !   !             !
            o   |             !
             L  |             !
              L |             !
               L|             !
                o-------------o ).volume == ( o-------------o
                                              |             !
                                              !             !
                                              !             !
                                              o-------------o ).area * int(I-------------I) );
josefx
источник
18
Хотя аналоговые литералы Eelis великолепны, являются ли они странной языковой функцией или просто странным способом использования этой функции?
85
Настоящий WTF будет ошибкой компилятора, сгенерированной одним из тех, кто искажен.
Эндрю МакГрегор
6
Как это плохо ... разбудите меня снова, когда есть версия AnalogLiterals, которая поддерживает вращение литерала вокруг осей X, Y и Z в Eclipse ... теперь это придаст "визуальному программированию" новый реальный смысл.
TheBlastOne
2
Имеет ли значение порядок «о», «л» и «а»?
Мин-Тан
4
Порядок имеет значение, так как шаблоны творчески используют перегрузку операторов (не делайте этого с реальным кодом, неправильное использование операторов затрудняет чтение кода)
josefx
292

Много встроенных переменных Perl:

  • $#- не комментарий!
  • $0, $$и $?- так же, как переменные оболочки с тем же именем
  • , $&И $'- странные сопоставления переменных
  • $"и $,- странные переменные для разделителей списков и выходных полей
  • $!- как errnoчисло, но strerror(errno)как строка
  • $_- стелс переменной, всегда и никогда не видел
  • $#_ - порядковый номер последнего аргумента подпрограммы ... возможно
  • @_ - (не) имена текущей функции ... возможно
  • $@ - последнее возбужденное исключение
  • %:: - таблица символов
  • $:, $^, $~, $-, И $=- что - то делать с выходными форматами
  • $.и $%- номер строки ввода, номер страницы вывода
  • $/и $\- разделители входных и выходных записей
  • $| - контроллер буферизации вывода
  • $[- измените базу массива с 0 на 1 на 42: WHEEE!
  • $}- вообще ничего, как ни странно!
  • $<, $>, $(, $)- реальные и эффективные UI и ГИД
  • @ISA - имена прямых суперклассов текущего пакета
  • $^T - время запуска скрипта в секундах эпохи
  • $^O - текущее имя операционной системы
  • $^V - что это за версия Perl

Там намного больше, откуда они пришли. Читайте полный список здесь .

Chris S
источник
83
$[Переменная является самым злым из всех.
Брэд Гилберт
24
Определенно был бы признателен, если бы Perl 6 был тем, что я мог бы написать без необходимости проверять perldoc perlvarкаждые пять секунд. (Хотя я признаюсь, что половину времени я проверяю это, думая: «Я знаю, что есть специальная переменная, которая может сделать это для меня, я просто не помню, какая из них ...» = P)
Крис Лутц
17
Проблема в use English;том, что это влияет на производительность RegExp. Я не придумываю это. perldoc.perl.org/English.html#PERFORMANCE
Дейв Уэбб
13
@Dave: это не проблема из-за опции -no_match_vars на странице, на которую вы ссылаетесь. @Brad: $ [ТАК ЗЛО. За этим стоит злая идея, да, но она также не работает! @Artem: from perlvar «Идентификаторы Perl, которые начинаются с цифр, управляющих символов или знаков пунктуации, освобождаются от последствий объявления пакета и всегда должны находиться в основном пакете; они также освобождаются от строгих ошибок 'vars'." Таким образом, это означает, что @ $ будет создан и назначен без ошибок даже в условиях строгости. Тьфу!
2010 года
4
@Brian: Как вы предлагаете изучать синтаксис, когда в официальной документации указано, что существуют обстоятельства, когда интерпретатор Perl эвристически догадывается, что означает последовательность символов? Например /$foo[bar]/, является ли [bar]часть символьным классом или индексом массива @foo? Grep Perldata за ужасающий ответ.
j_random_hacker
289

PHP обрабатывает числовые значения в строках . Смотрите этот предыдущий ответ на другой вопрос для более подробной информации, но, вкратце:

"01a4" != "001a4"

Если у вас есть две строки, содержащие разное количество символов, их нельзя считать равными. Ведущие нули важны, потому что это строки, а не числа.

"01e4" == "001e4"

PHP не любит строки. Он ищет любое оправдание, которое может найти ваши значения как числа. Немного измените шестнадцатеричные символы в этих строках, и вдруг PHP решит, что это уже не строки, это числа в научной нотации (PHP не заботится о том, что вы использовали кавычки), и они эквивалентны, так как начальные нули игнорируются для чисел. Чтобы подтвердить это, вы обнаружите, что PHP также оценивается "01e4" == "10000"как true, потому что это числа с эквивалентными значениями. Это документированное поведение, просто оно не очень разумно.

Dan Dyer
источник
56
Просто используйте === и! ==. Который должен использоваться в любом случае, если не требуется свободного сравнения типов.
Dykam
14
@Dykam, если вы перейдете по ссылке на более полный ответ, то увидите, что я рассмотрел использование оператора ===.
Дэн Дайер
18
Слабый набор ударов снова!
Гиллонба
43
Я всегда знал, что PHP - это грех. До сих пор я не осознавал, что это был непростительный грех: D
Томас Эдинг
2
Они должны быть техническими людьми, чтобы использовать === в любой книге или учебнике по программированию. Добавлено примечание: В плохо написанном PHP-приложении я смог указать в качестве пароля все, что было проанализировано с тем же номером.
Пепейн
282

Давайте проголосуем за все языки (такие как PL / I), которые пытались избавиться от зарезервированных слов.

Где еще вы могли бы легально написать такие забавные выражения, как:

IF IF THEN THEN = ELSE ELSE ELSE = THEN

( IF, THEN, ELSEЯвляются имена переменных)

или

IF IF THEN THEN ELSE ELSE

( IFявляется переменной, THENи ELSEподпрограммы)

MZB
источник
1
@ Quark: это отдельный ответ на это! ;) ... (и да, вы можете программировать на английском языке, просто разверните его как .ppt для других разработчиков.;)
Macke
28
@RoadieRich одна группа буйволов явно не из Буффало, они просто неописуемые буйволы.
Юрген А. Эрхард
18
Джон, где раньше был Джеймс, оказал лучшее влияние на учителя.
GameFreak
4
На днях я видел некоторых производителей вывесок возле фабрики мороженого Бена и Джерри. Я критиковал их работу, я говорил им, что между Беном, и, и, и, и, и, Джерри, недостаточно места.
Том Гуллен
9
Возможно, это понадобится для будущих временных программ. ЕСЛИ ТОГДА = СЕЙЧАС && ГДЕ = ЗДЕСЬ ТОГДА КОГДА = ТАК ДАЖЕ СЕЙЧАС = ДРУГОЙ
Kelly S. French
282

Полезно знать о «восьмеричном» преобразовании JavaScript:

parseInt('06') // 6
parseInt('07') // 7
parseInt('08') // 0
parseInt('09') // 0
parseInt('10') // 10

Подробнее здесь .

Брайан Детерлинг
источник
60
Застрял на ошибке, что все числа работали, кроме 8 и 9! Схожу с ума !!! Спасибо, Брайан!
Фаруз
10
@Yada Вы не имеете в виду восьмеричный? Шестнадцатеричный 0x.
luiscubal
48
И именно поэтому parseInt принимает (необязательный) дополнительный аргумент :).
LiraNuna
10
ведущий 0 означает восьмеричное число. поскольку 8 не является действительной восьмеричной цифрой, результат должен быть 0.
devio
22
... и parseInt ('010') -> 8, чтобы сбить вас с толку.
Ричард Гадсден
213

Устройство Даффа в C!

В C можно сделать do / while с помощью оператора switch. Вот пример memcpy, использующего этот метод:

void duff_memcpy( char* to, char* from, size_t count ) {
    size_t n = (count+7)/8;
    switch( count%8 ) {
    case 0: do{ *to++ = *from++;
    case 7:     *to++ = *from++;
    case 6:     *to++ = *from++;
    case 5:     *to++ = *from++;
    case 4:     *to++ = *from++;
    case 3:     *to++ = *from++;
    case 2:     *to++ = *from++;
    case 1:     *to++ = *from++;
            }while(--n>0);
    }
}
Frunsi
источник
9
Устройство Даффа, вероятно, является хорошей причиной того, что оператор switch по умолчанию не имеет разрыва ;-) Однако я еще не видел какого-либо другого хорошего использования чересстрочного переключателя и цикла - но, вероятно, есть один. Ой, подождите, да, есть другое применение: сопрограммы и протопотоки.
Фрунси
16
@frunsi: «Устройство Даффа, вероятно, является хорошей причиной того, что оператор switch не имеет по умолчанию разрыва» - всегда делайте общий случай по умолчанию. Я бы точно не сказал, что это частый случай ..
BlueRaja - Дэнни Пфлюгофт
6
@mcv, вероятно, проще всего, если вы попытаетесь прочитать его как ассемблерный код, т. е. whileв конце (условный) JMPвозврат к do, что объясняет, почему вы можете пропустить doи все же оказаться в цикле.
2010 года
14
Имейте в виду, что устройство Даффа обычно генерирует код WORSE, чем обычный оператор зацикливания для современных компиляторов, которые знают, как (лучше) развернуть цикл, чем вы можете сделать вручную.
Билли ОНил
37
@frunsi: Дафф сам, публикуя его, утверждал что-то вроде этого: «Это определенно дает аргумент в дискуссии о том, должен ли переключатель падать по умолчанию, но я не уверен, что аргумент за или против»
SF.
204

Алгол, передаваемый по имени (показано с использованием синтаксиса C):

int a[3] = { 1, 2, 3 };
int i = 1;

void f(int j)
{
    int k;
    k = j;  // k = 2
    i = 0;
    k = j;  // k = 1 (!?!)    
}

int main()
{
    f(a[i]);
}
Richard Pennington
источник
33
Если вы думаете об этом, это действительно имеет какой-то извращенный смысл
RCIX
90
Это в конечном итоге "передать по ссылке".
Dykam
3
Это возможно в Scala, хотя ( def f(j : => int))
Дарио
10
Так это что-то вроде ... template<typename T> struct by_name { virtual operator T&() = 0; }; void f(by_name<int> j) { ... } int main() { f(struct : by_name<int> { operator int&() { return a[i]; } }); }?
Саймон Бьюкен
2
Это на самом деле довольно просто: вы генерируете небольшой фрагмент кода (обычно называемый «thunk», отсюда и мой каламбур выше), который вычисляет адрес, полученный из выражения, в данном случае & a [i]. Указатель на эту функцию передается вызываемой функции, которая затем использует ее для вычисления текущего адреса при каждом обращении к параметру.
Ричард Пеннингтон
189

В Python:

>>> x=5
>>> 1<x<10
True
>>> 1<x<3
False

Не WTF, но полезная функция.

MAK
источник
176
Я хотел бы, чтобы у всех других языков была эта особенность
vava
32
Как и почти все классные функции Python, похоже, что Гвидо просто-напросто по-алголизировал синтаксис классной функции Lisp. :-)
Кен
4
Джеффри, это особенность, и (10 > 5 > 1) != ((10 > 5) > 1)в Python.
Састанин
18
Кроме того, он оценивает только один раз, поэтому (funct_a(5)+5 > b > funct_a(5))звонит только funct_a(5)один раз. Это отличная особенность!
Хелбен
57
@Khelben: Нет, funct_aв этом примере будет вызываться дважды. В b > funct_a(5) > cэто будет вызван только один раз, в отличие от b > funct_a(5) and funct_a(5) > c.
Баффе Бойуа
189

В Java:

int[] numbers() {
  return null;
}

Может быть написано как:

int numbers() [] {
  return null;
}
Chandra Patni
источник
23
Вот Это Да! Хотел бы я быть мухой на стене, когда был разработан этот синтаксис массива!
Адам Пейнтер
29
Я не хочу говорить это, но WTF - последовательное расширение системы типов C. Если бы функциям C было разрешено возвращать массивы, то это было бы так. Более приятное нарушение целостности делает его более читабельным. Очень похоже на "const char * var" против "char const * var".
Гордон Ригли
15
@Adam - Это действительно имеет смысл, если учесть, что объявление переменных одинаково разрешает и «int stuff []», и «int [] stuff». Они просто позволяют тем же правилам работать для объявления метода.
Брэндон Ярбро
2
@lImbus: На самом деле, const T*и T const*это эквивалентно, это T* constуказатель. Кроме того, я ненавижу без шрифтов.
Симон Бьюкен
3
В конце концов, numbers()[2]это юридическое заявление.
Badp
184

INTERCAL , вероятно, лучший сборник самых странных языковых возможностей. Мой личный фаворит - это утверждение COMEFROM, которое (почти) противоположно GOTO.

COMEFROM примерно противоположен GOTO в том смысле, что он может переносить состояние выполнения из любой произвольной точки кода в оператор COMEFROM. Точка в коде, где происходит передача состояния, обычно указывается в качестве параметра COMEFROM. Происходит ли перевод до или после инструкции в указанном пункте передачи, зависит от используемого языка. В зависимости от используемого языка, несколько COMEFROM, ссылающихся на одну и ту же точку отправления, могут быть недопустимыми, быть недетерминированными, выполняться с определенным приоритетом или даже вызывать параллельное или иным образом параллельное выполнение, как это видно в многопоточном интеркале. Простым примером оператора «COMEFROM x» является метка x (которая не обязательно должна быть физически расположена где-то рядом с его соответствующим COMEFROM), которая действует как «дверь-ловушка». Когда выполнение кода достигает метки, управление передается оператору после COMEFROM. Результатом этого является прежде всего затруднение отладки (и понимания потока управления программой), поскольку рядом с меткой нет указания, что управление таинственным образом перейдет в другую точку программы.

Джефф Фостер
источник
16
Совершенно зло - превращает ярлыки в GOTO. Похоже на то, что хакеры просят о языковой особенности ...
RCIX
114
Хорошо, но INTERCAL должен быть забавным - это не совсем удивительная "ошибка". INTERCAL-компилятор может фактически отказаться от компиляции программы, если вы не используете PLEASEмодификатор достаточно часто!
Groo
10
Звуки , как АОП :)
akuhn
6
Что меня больше всего удивляет, так это то, что при анализе системных требований в «World of Commercial TI» COMEFROM фактически используются в текстовых файлах, описывающих варианты использования. (серьезно: некоторые аналитики здесь задержали переход всей корпорации на OpenOffice вместо MS Office, поскольку первый не мог правильно ссылаться на «comefrom» с необходимой детализацией в ссылке)
jsbueno
5
Гру: Это хуже. Используйте PLEASE слишком часто, и он отказывается компилировать вашу программу, потому что вы унижаетесь (C-INTERCAL требует, чтобы от 33% до 66% операторов имели модификаторы PLEASE).
Ватин
160

Не совсем языковая особенность, но недостаток реализации: некоторые ранние компиляторы Фортрана реализовывали константы, используя постоянный пул. Все параметры были переданы по ссылке. Если вы вызвали функцию, например

f(1)

Компилятор передал бы адрес константы 1 в пуле констант функции. Если вы присвоили значение параметру в функции, вы изменили бы значение (в данном случае значение 1) глобально в программе. Вызвало некоторые царапины на голове.

Ричард Пеннингтон
источник
124
Ooh. Тогда 2+2 может равняться 5(для очень больших значений 2конечно!).
Алок Сингхал
12
хм, какое значение 2 будет равно "2 + 2" == "5"? Я не знаю ни одного целочисленного значения 2, которое могло бы быть правдой.
Аарон
36
@earlz: я подозреваю, что это будет целостное значение любой битовой комбинации. С другой стороны, вы могли бы, вероятно, установить 5 к 4 таким образом (так 2+2будет равно 5для небольших значений 5).
Дэвид Торнли
18
Извини меня, Алок, но это ранний Фортран, о котором мы говорим. Это не будет правдой 2 + 2 = 5; это будет синтаксическая ошибка. Что будет верно это 2 + 2 .EQ. 5.
Дэвид Торнли
3
В Haskell следующий фрагмент оценивается как 5: «let 2 + 2 = 5 in 2 + 2» :)
Tirpen
153

Не знаю, можно ли это считать языковой функцией, но в C ++ практически любая ошибка компилятора, связанная с шаблонами, ежедневно доставляет немало WTF многим программистам C ++ по всему миру :)

Дмитрий
источник
15
Это нормально, большинство кода, связанного с шаблонами, уже создает множество WTF по всему миру.
Йорис Тиммерманс
43
Ох, давай сейчас. неопределенная ссылка на `std :: basic_ostream <char, std :: char_traits <char>> & std :: operator << <std :: char_traits <char>> (std :: basic_ostream <char, std :: char_traits <char> > &, char const *) «Отлично читается!
Мэтт Грир
10
Однажды у меня была ошибка компилятора, связанная с шаблоном, которая состояла из пяти строк, самая короткая из которых составляла семнадцать тысяч символов (классическая ошибка «нет совпадения для x» в программе с глубокими шаблонами). Это WTF, а не особенность, шаблоны замечательные.
Эндрю МакГрегор
111
Даже если нет ошибок, попробуйте найти, какие функции работают дольше всего с вашим профилировщиком. О, смотри, этоstd::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::vector< std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator>(std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator, std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator, std::allocator<std::pair<int, std::complex> >)
rlbond
12
Я думаю, что это подходит здесь: Проверьте STLFilt на bdsoft.com/tools/stlfilt.html, чтобы сделать вывод читабельным.
Foraidt
150

Много пространств имен C:

typedef int i;

void foo()
{
    struct i {i i;} i;
    i: i.i = 3;
    printf( "%i\n", i.i);
}

Или с персонажами:

typedef char c;

void foo()
{
    struct c {c c;} c;
    c: c.c = 'c';
    printf( "%c\n", c.c);
}
Victor Hurdugaci
источник
Как, черт возьми, это компилируется однозначно !?
Эрлз
13
+1 Идентификаторы тегов для перечислений и структур - самая запутанная часть языка C imho. Мало кто понимает, почему идиома для определения типа указателя на структуру выглядит так, как она.
Тадеуш А. Кадлубовски
11
Он компилируется, потому что у каждого из тех, кто у меня есть, есть однозначное пространство имен из-за контекста.
Эндрю МакГрегор
149

Я бы сказал, что вся штука с пробелами в Python - моя лучшая особенность WTF. Правда, через некоторое время вы более или менее привыкаете к этому, и современные редакторы позволяют легко с этим справляться, но даже после большей части разработки Python в течение полного года я все еще убежден, что это плохая идея. Я прочитал все причины этого, но, честно говоря, это мешает моей производительности. Не очень, но это все еще заусенец под седлом.

редактировать: судя по комментариям, некоторые люди думают, что я не люблю делать отступы в своем коде. Это неверная оценка. Я всегда смещал свой код независимо от того, на каком языке и был ли я вынужден или нет. Что мне не нравится, так это то, что именно отступ определяет блок, в котором находится строка кода. Я предпочитаю для этого явные разделители. Среди прочих причин я обнаружил, что явные разделители облегчают вырезание и вставку кода.

Например, если у меня есть блок с отступом 4 пробела и вставьте его в конец блока с отступом 8 пробелов, мой редактор (все редакторы?) Понятия не имеет, принадлежит ли вставленный код блоку из 8 пробелов или внешнему блок. OTOH, если у меня есть явные разделители, становится очевидным, к какому блоку принадлежит код и как он должен (пере) отступаться - это происходит благодаря интеллектуальному поиску разделителей блоков.

редактировать 2: некоторые люди, которые предоставляют комментарии, кажется, думают, что это функция, которую я ненавижу или которая, я думаю, делает Python плохим языком. Опять не правда. Хотя мне это не очень нравится, это не относится к делу. Вопрос о странной языковой функции, и я думаю, что это странно, потому что она используется очень, очень немногими (но> 0) языками.

Брайан Окли
источник
63
если это повлияет на вашу производительность, тогда ваш непитоновский код не может быть очень читабельным ...
Tor Valamo
27
Какой язык вы использовали до Python? Как вы могли работать с другими людьми и не отступать от этого языка? Как можно мириться с кодом без отступов на любом языке? Вы работали в комнате, полной гениев, которым не нужны визуальные подсказки в исходном коде?
С.Лотт
53
+1 Не могу согласиться, если мой редактор (Emacs) не может автоматически сделать отступ для моего кода, основанного на чем-то особенном (например, фигурные скобки / начало, конец / вы называете это), это серьезно глупо. Практически любой рефакторинг, который вы выполняете для «большей» функции, может быть очень плохим опытом.
Дмитрий
83
Вот в чем дело - с любым другим языком я могу выделить блок кода и правильно его отступить в любом редакторе. Но поскольку пробел по определению является правильным отступом, вы теряете эту способность в Python. Так что сложнее перемещать код или реорганизовывать вещи. И для человека, который утверждает, что OP является «первым человеком, который заявил, что это была проблема», ну, мне пришлось некоторое время поддерживать некоторый код на Python, и теперь я буду использовать любой язык поверх Python по этой самой причине.
Кендалл Хельмштеттер Гелнер
38
Я не возражаю против пробелов в Python. WTF заключается в том, что он не применяется последовательно. Вы можете смешивать уровни отступов и вкладки, если они соответствуют своим братьям и сестрам. Таким образом, первый уровень отступа может быть одним пробелом, а второй - двумя табуляциями, и это не является синтаксической ошибкой.
2010 года
138

Я немного боролся по этому поводу:

1;

В Perl модули должны возвращать что-то истинное .

Мик
источник
29
Некоторые модули могут возвращать значения в зависимости от операций во время выполнения. Если вы всегда возвращаете true, вам все равно не нужно быть не очень креативным
Anonymous
8
Если моя память Perl обслуживает меня правильно, возвращение true из модуля указывает, что модуль загружен успешно. Возврат ложного значения означал, что что-то пошло не так и предотвратил запуск программы (если ее не поймали).
Барри Браун
Это также допустимый оператор C, только ничего не возвращается.
sigjuice
24
Марк Доминус писал: «Я очень редко использовал, 'Cogito ergo sum';что, как всем известно, самоочевидно верно во всех возможных вселенных. Это обеспечивает максимальную переносимость».
Грег Бэкон
PHP <?=1;?>возвращает 1. <?=true;?>возвращает 1. <?=false;?>возвращает ноль.
Талви Ватиа
135

Я удивлен, что никто не упомянул 7 циклических конструкций Visual Basic .

For i As Integer = 1 to 10 ... Next
While True ... End While
Do While True ... Loop
Do Until True ... Loop
Do ... Loop While True
Do ... Loop Until True
While True ... Wend

Потому что наклеить! перед вашим Conditional является способом слишком сложно!

Jeff Atwood
источник
47
Они должны были сделать это « Whileи Whend», поскольку есть некоторые люди, которые произносят слово «пока» с глухим лабиализированным приближением велярного. И, конечно, он выстраивается лучше, и код, который выстраивается, хорош.
Dreamlax
43
Почему ты ведешь себя так странно?
Эрик Форбс
48
Ух ты. Я чувствую ностальгию, когда думаю об этом. Впервые я использовал VB, когда мне было 9 лет. Я из Швеции, и тогда я не очень хорошо знал английский. Теперь есть шведское слово, называемое «vänd», которое в основном означает «повернуть назад» и произносится как «wend». Из-за этого я думал, что это имело большой смысл ... :)
Эмиль Х
61
! не в VB, это "не". Или это? Да, нет, но нет.
brianary
7
Да, «Wend» - это английское слово, означающее идти или идти по какому-либо курсу или маршруту ( google.com/search?q=define%3A+wend ). Я не уверен, помогает ли это или причиняет боль.
Майкл Майерс
134

Для тех, кто не знает, bcэто «язык калькулятора произвольной точности», и я использую его довольно часто для быстрых вычислений, особенно когда задействованные числа являются большими ( $подсказка):

$ bc -lq
12^345
20774466823273785598434446955827049735727869127052322369317059031795\
19704325276892191015329301807037794598378537132233994613616420526484\
93077727371807711237016056649272805971389591721704273857856298577322\
13812114239610682963085721433938547031679267799296826048444696211521\
30457090778409728703018428147734622401526422774317612081074841839507\
864189781700150115308454681772032

bcдолгое время была стандартной командой Unix .

Теперь о «функции WTF». Это из man bc(выделение мое):

quit : при прочтении оператора quit процессор bc завершается независимо от того, где находится оператор quit. Например, «if (0 == 1) quit» приведет к завершению bc.

halt : оператор halt (расширение) является оператором execute, который заставляет процессор bc завершать работу только при его выполнении. Например, «if (0 == 1) halt» не приведет к завершению bc, поскольку останов не выполняется.

Алок
источник
41
Я использую Haskell для этого материала.
Томас Эдинг
8
Гугл калькулятор?
igul222
7
Я сам начал использовать Python, и гугл калькулятор хорош, если вы онлайн. Но раньше я использовал bcэто и хотел написать bcв своем посте из-за замечательных цитат из справочной страницы.
Алок Сингхал
6
@ Брайан, тогда вам понравится: echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc(хотя вы, возможно, уже знаете это).
Алок Сингхал
2
Я использую irb (Ruby интерактивная оболочка). Но в свое время я всегда тянулся к dc - как bc, но использовал обратную полировку. Geektastic!
трагомасхалось
134

Я всегда задавался вопросом, почему самая простая программа была:

class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

Тогда как это может быть:

print "Hello World!"

Может быть, это пугает студентов по информатике в первую очередь ...

Didier Trosset
источник
34
На некоторых языках "Hello World!" является действительной программой
Дэвид Торнли
31
@SoMoS: на большинстве динамических языков, таких как Python, Ruby или Perl, выведите «Hello World!» или некоторые незначительные изменения (например, помещает вместо печати) является действительной и полной программы.
Дэйв Кирби
36
@Loadmaster: подразумевалось, что «весь код принадлежит классу» или «весь код принадлежит функции» - это ненужные ограничения
Джимми
19
Тот факт, что язык навязывает использование объектов, не означает, что он используется для правильного объектно-ориентированного программирования. Можно процедурно программировать на Java или C #. Вот для чего нужны статические методы.
2010 года
68
Я люблю людей, которые думают, что ООП означает, что все должно быть объектом.
Тор Валамо
132

JavaScript является объектно-ориентированным, верно? Таким образом, методы работы на литеральных строках и числах должны работать. Вроде "hello".toUpperCase()и 3.toString(). Оказывается, что вторая ошибка синтаксиса, почему? Поскольку синтаксический анализатор ожидает, что число, сопровождаемое точкой, является литералом с плавающей запятой. Это не WTF, WTF в том, что вам нужно только добавить еще одну точку, чтобы она заработала:

3..toString()

Причина в том, что литерал 3.интерпретируется как 3.0и 3.0.toString()работает нормально.

Тео
источник
8
Так же работает и в Python (попробуйте 3..__add__(4)). Опять же, я думаю, что (3).__add__(4)это гораздо менее поврежденный мозг способ сделать это :)
badp
49
Вы можете просто сделать (3) .toString ()
Джозеф Монтанес
13
@ Gorilla3D: да, но это не странная языковая особенность, не так ли?
Тео
25
3.0.toString()Зудит мои глаза.
Бен Бланк
18
127.0.0.1.toInt ()
berkus
130

В JavaScript:

2 == [2]

// Even stranger
2 == [[[2]]]

// And down-right nutty
var a = { "abc" : 1 };
a[[[["abc"]]]] === a["abc"]; // this is also true

К счастью, добрые ребята из stackoverflow.com объяснили мне все это: почему 2 == [2] в JavaScript?

Xavi
источник
6
Вот почему вы должны использовать ===вместо этого.
Гамбо
10
Это полезно, кстати, если у вас есть функция, которая возвращает число, и вы хотите вернуть некоторые дополнительные метаданные с ним, вы можете вернуть [число] с добавлением некоторых дополнительных полей. Простой код никогда не узнает, что это не действительное число, а другой код может получить необходимые метаданные.
Андрей Щекин
36
@ Андрей, за исключением того, что если мне когда-нибудь придется поддерживать код, который делает то, что вы предлагаете, я бы очень скоро пожелал смерти его автору.
Бретон
@ Андрей, это отличная идея! Вы также можете использовать, Number(n)чтобы сделать что-то подобное. К сожалению в обоих наших решениях ===перерывы = (.
Хави
5
+1: я считал себя опытным программистом JS, и я никогда не знал об этом: D
Томас Эдинг
126

Моя самая большая ненавистная особенность - любой синтаксис файла конфигурации, который включает условную логику. Подобные вещи распространены в мире Java (Ant, Maven и т. Д. Вы знаете, кто вы есть!).

Вы просто заканчиваете программирование на ac ** p языке, с ограниченной отладкой и ограниченной поддержкой редактора.

Если вам нужна логика в вашей конфигурации, «Pythonic» подход кодирования конфигурации на реальном языке будет намного лучше.

Джеймс Андерсон
источник
24
Tcl заново изобрел это задолго до рождения Python, а Лисп изобрел его до этого. Так что давайте не будем называть это Pythonic, давайте назовем это Emacs-ish.
Slebetman
46
Давайте просто назовем это правильно.
mletterle
30
АМИНЬ. Если ваша конфигурация или язык сборки завершены, вы делаете это неправильно. Я смотрю на тебя CMake / autotools.
Джозеф Гарвин
16
Это именно то, для чего изначально был разработан Lua
Cogwheel
1
Что ж, если ваш код написан на Python, то иметь ваш файл конфигурации в виде файла Python - отличная идея, потому что вы просто импортируете файл и прочитаете атрибуты модуля. И вы получите 100% Turing Complete для Python в своем конфигурационном файле.
asmeurer
113

powerbasic (www.powerbasic.com) включает директиву компилятора:

# BLOAT {bloatsize}

это увеличивает размер скомпилированного исполняемого файла в <bloatsize>байтах. это было помещено в компилятор на тот случай, если людям, создающим исполняемый файл, не нравится маленький размер сгенерированного исполняемого файла. это заставляет EXE казаться больше, чтобы конкурировать с раздутыми языками программирования :)

Дон Дикинсон
источник
9
Хаха юк. Я слышал о разработчиках, намеренно замедляющих некоторые операции (например, поиск), потому что это помогает людям поверить, что он действительно что-то делает. Подобная вещь, я думаю.
Дэвид
42
Это напоминает мне кое-что, что я недавно прочитал. Они тестировали FPS и решили увеличить количество очков жизни у плохих парней. Затем они спросили тестеров, как у них дела с ИИ, и поклялись, что это намного умнее. Но ИИ не изменился, только очки жизни. У людей есть определенный рассказ о мире в их головах, и если вы понимаете и соответствуете их ожиданиям, они просто предполагают, что это подтверждает их повествование.
Nate CK
5
Раньше я добавлял много дополнительных замедлений в свои программы, чтобы они выглядели так, как будто они делают что-то сложное. Вернемся в начальную школу.
Матти Вирккунен
3
Еще в школе у ​​нас было 80286 машин, и мне фактически пришлось написать некоторые процедуры вывода на экран в сборке, чтобы получить разумную скорость (т.е. не сканировать).
Беркус
7
@Nate CK, если ИИ живет достаточно долго, чтобы хвастаться своим ИИ, он на самом деле может быть умнее, тогда как раньше он мог умереть слишком быстро, чтобы доказать это.
zzzzBov