Самая странная функция языка

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

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

975
задан Andreas Bonini 03 янв. '10 в 17:27
источник поделиться
320 ответов

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

a[10]

который очень распространен.

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

10[a]

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

1861
ответ дан Edan Maor 03 янв. '10 в 17:41
источник поделиться

В JavaScript:

 '5' + 3 gives '53'

В то время как

 '5' - 3 gives 2
1296
ответ дан Dipstick 03 янв. '10 в 18:39
источник поделиться

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

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

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

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

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

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

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

return
    2 + 2;
872
ответ дан Tamas Czinege 05 янв. '10 в 3:12
источник поделиться

Таблица истинности 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

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

797
ответ дан Chandra Patni 04 янв. '10 в 11:34
источник поделиться

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

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

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

662
ответ дан Andreas Bonini 03 янв. '10 в 17:32
источник поделиться

Развлечения с автоматическим боксом и целым кешем в 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), поэтому при сравнении эталонного равенства они будут истинными, а не ложными. Правильный способ сравнения значения Integer использует .equals;

574
ответ дан z - 04 янв. '10 в 23:06
источник поделиться

Цитата Neil Fraser (посмотрите на конец этой страницы),

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

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

EDITED: Пока мы обсуждаем этот вопрос:

try {
    throw new AssertionError();
} finally {
    return false;
}
373
ответ дан lorenzog 05 янв. '10 в 13:44
источник поделиться

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

например. Conway Game of Life в одной строке в APL:

alt text http://catpad.net/michael/APLLife.gif

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

И вот видео

325
ответ дан lkessler 05 янв. '10 в 6:10
источник поделиться

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

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

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

Или, еще один пример с 3D-кубом:

  assert( ( o-------------o
            |L             \
            | L             \
            |  L             \
            |   o-------------o
            |   !             !
            !   !             !
            o   |             !
             L  |             !
              L |             !
               L|             !
                o-------------o ).volume == ( o-------------o
                                              |             !
                                              !             !
                                              !             !
                                              o-------------o ).area * int(I-------------I) );
322
ответ дан josefx 08 янв. '10 в 2:50
источник поделиться

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

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

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

292
ответ дан Chris S 04 янв. '10 в 0:06
источник поделиться

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

"01a4" != "001a4"

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

"01e4" == "001e4"

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

289
ответ дан Dan Dyer 03 янв. '10 в 17:58
источник поделиться

Функция восьмеричного конвертирования JavaScript - это хорошая информация о:

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

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

282
ответ дан Brian Deterling 05 янв. '10 в 6:12
источник поделиться

Позвольте голосовать за все языки (например, PL/I), которые пытались покончить с зарезервированными словами.

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

IF IF THEN THEN = ELSE ELSE ELSE = THEN

(IF, THEN, ELSE - имена переменных)

или

IF IF THEN THEN ELSE ELSE

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

282
ответ дан MZB 05 янв. '10 в 7:24
источник поделиться

Устройство Duff в 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);
    }
}
214
ответ дан Frunsi 07 янв. '10 в 5:41
источник поделиться

Алгол проходит по имени (иллюстрируется синтаксисом Си):

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]);
}
204
ответ дан Richard Pennington 03 янв. '10 в 17:55
источник поделиться

В Java:

int[] numbers() {
  return null;
}

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

int numbers() [] {
  return null;
}
190
ответ дан Chandra Patni 04 янв. '10 в 11:10
источник поделиться

В Python:

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

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

189
ответ дан MAK 03 янв. '10 в 23:04
источник поделиться

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

COMEFROM примерно противоположна GOTO в том, что он может выполнить казнь состояние из любой произвольной точки кода к заявлению COMEFROM. Точка в код, в котором происходит передача состояния обычно задается как параметр для РОДОМ ИЗ. Передача происходит до или после инструкции на указанная точка передачи зависит от используемый язык. В зависимости от язык, несколько COMEFROM ссылаясь на ту же точку отправления может быть недействительным, быть недетерминированным, выполняться в некотором приоритет или даже вызвать параллельные или в противном случае одновременное выполнение, как видно в Threaded Intercal. Простой пример оператора "COMEFROM x" является ярлыком x (что не обязательно должно быть физически расположенный где угодно соответствующий COMEFROM), который действует как "ловушка". При выполнении кода достигает метки, контроль проходит к заявлению, следующему РОДОМ ИЗ. Эффект этого прежде всего для отладки (и понимание управляющего потока программы) чрезвычайно сложно, поскольку рядом с меткой нет указателя этот контроль таинственно перескочит другая точка программы.

184
ответ дан Jeff Foster 03 янв. '10 в 18:30
источник поделиться

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

f(1)

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

160
ответ дан Richard Pennington 03 янв. '10 в 19:37
источник поделиться

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

153
ответ дан Dmitry 03 янв. '10 в 19:31
источник поделиться

Множество пространств имен 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);
}
150
ответ дан Victor Hurdugaci 04 янв. '10 в 19:15
источник поделиться

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

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

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

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

149
ответ дан Bryan Oakley 03 янв. '10 в 18:31
источник поделиться

Я немного поболтал об этом:

1;

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

138
ответ дан miku 03 янв. '10 в 17:28
источник поделиться

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

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

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

135
ответ дан Brian Postow 04 янв. '10 в 18:03
источник поделиться

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

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

В то время как это может быть:

print "Hello World!"

Возможно, это в первую очередь пугает студентов-информатиков...

134
ответ дан Didier Trosset 04 янв. '10 в 11:05
источник поделиться

Для тех, кто этого не знает, 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 (расширение) является выполненным оператором, который заставляет процессор bc выйти только тогда, когда он выполняется. Например, "if (0 == 1) halt" не приведет к завершению работы bc, потому что остановка не выполняется.

134
ответ дан Alok Singhal 03 янв. '10 в 20:34
источник поделиться

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

3..toString()

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

132
ответ дан Theo 21 июля '10 в 11:18
источник поделиться

В 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?

130
ответ дан Xavi 04 янв. '10 в 10:40
источник поделиться

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

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

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

126
ответ дан James Anderson 04 янв. '10 в 5:04
источник поделиться

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

# BLOAT {bloatsize}

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

113
ответ дан Don Dickinson 07 янв. '10 в 6:55
источник поделиться

Другие вопросы по меткам