Найстрашніша особливість мови


974

Яка, на ваш погляд, найдивовижніша, дивна, дивна чи справді мовна особливість "WTF", з якою ви стикалися?

Будь ласка, лише одна функція на відповідь.


5
@gablin Я думаю, якщо ви поєднали роздільники LISP з PERL-регексом за допомогою розбору JavaScript, ви покрили б 90% WTF ...
Talvi Watia,

Відповіді:


1859

В C масиви можна проіндексувати так:

a[10]

що дуже часто.

Однак менш відома форма (яка справді працює!) - це:

10[a]

що означає те саме, що вище.


758
це тому, що a [10] означає * (a + 10) ... а 10 [a] означає * (10 + a) :)
Мішель Гокан

77
Не забувайте "Hello Hello" [i]. Або я ["Hello World"]
Річард Пеннінгтон

167
Або, що більш корисно, "0123456789abcdef" [х & 0xf]
Щуп

17
@frunsi: Це завжди працює так, як очікувалося. Додавання покажчика не те саме, що просте додавання цілих чисел на адреси. Це комутативно, незалежно від розміру, про який йдеться.
Р. Мартіньо Фернандес

12
@mcv - a [10] - це те саме, що "* (a + 10)", де вираз "a + 10" є арифметичним покажчиком (а оскільки a - короткий, у вашому прикладі, a + 10 означає "start at адресу та перемістіть 10 шортів, тобто 20 байт '). Вираз 10 [a] інтерпретується як "* (10 + a)", де "10 + a" також є арифметикою вказівника, і трактується точно так само.
Edan Maor

1292

У JavaScript:

 '5' + 3 gives '53'

Тоді як

 '5' - 3 gives 2

81
Я пам’ятаю, коли я вперше почав використовувати javascript, використовуючи подібну техніку для додавання чисел у рядках: «111» - - «222» дає 333, тоді як «111» + «222» дає «111222».
Callum Rogers

112
+для струнної конкатенації жахливо
Маттео Ріва

416
+ для concat не проблема. Слабке введення є.
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;

225
Вставка крапки з комою є однією з найбільш злих частин JavaScript.

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

8
У мене насправді була ця проблема, будучи самим розробником c #, я поставив брекет у новий рядок. Мені потрібні години, щоб зрозуміти, в чому проблема. Навіть коли я вирішив питання, я не знав, в чому проблема, поки не прочитав вашу відповідь!
Федір Хайду

24
Нік Реталак: Оскільки через синтаксис фігурних дужок і напівколонок JavaScript схожий на JavaScript, зовсім не видно, що нові рядки є значущими.
Тамас Цінеге

19
Якщо ви не повинні використовувати стиль C під час програмування в JavaScript, тоді дизайнерам мови JavaScript було досить перекручено вибрати синтаксис стилю С.
Райан Лунді

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

Джерело: Даг Крокфорд


237
Добре, що у Javascript є оператор ===, значить.
Анонім

65
Тож яка мета ==служить очам дизайнера мови?
Chris S

137
Заплутаність людей.
Хав'єр

123
Було б добре, якби ==мав сенс ===, а тоді з’явився інший оператор, щось подібне ~=дозволяло вводити примус.
ТМ.

18
@Otto фактично, оскільки ми шукаємо, його приклад показує, що == не симетричний. На даний момент я не бачив, як комунікативність буде визначена для бінарного відношення.
PeterAllenWebb

660

Триграфи в С і С ++.

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

Це буде надруковано LOL|, оскільки триграф ??!перетворений у |.


71
Швидкий! Розкажіть усім C / b / програмістам!
Естебан Кюбер

235
Триграфи дивовижні, адже ти можеш бути впевнений, що ніхто не дізнається, що таке! означатиме від Google, не знаючи імені вже.
zaratustra

56
Триграфи за замовчуванням відключені в GCC.
зустріч

360
Вони дозволяють вам використовувати "WTF-оператор": (foo ()! = ПОМИЛКА) ??! ??! cerr << "Виникла помилка" << endl;
користувач168715

57
Триграфи були необхідним злом, коли вони були представлені. Деякі платформи просто не включали певні символьні ключі до мови, тому це були або "триграфі", або "ви не можете мати компілятор C, період закінчення оператора, тому перейдіть на використання асемблера". Ознайомтесь з описом Stroustrup у "Мові програмування на 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;


31
Знадобилося мені пару секунд, щоб зрозуміти, чому ... java повинен зберігати пул екземплярів Integer для значень між -128 і 128, інакше він виділяє новий Integer, правда?
Майк Акерс

18
проте майте на увазі, що якщо ви вкажете новий Integer (42), він не буде використовувати примірник з пулу, тому foo == bar оцінить значення false
z -

10
Я завжди використовую Ints замість Integers, якщо можливо, але якщо мені довелося використовувати Integers з якихось причин, я повинен просто використовувати .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. Чомусь я вважаю це веселим і не можу перестати хихикати.
outis

153
На щастя, C # не допускає такого божевілля ...Control cannot leave the body of a finally clause
Річард Ев

64
Це повертається, помилково, чи не так? Це може виглядати як WTF (і, можливо, це один), але я живу за правилом: Нарешті, завжди виграє, якщо ви не зірвете машину раніше.
Майкл Стум

28
Чесно кажучи, я звинувачую приємне пояснення TDWTF за те, що пам’ятати, що нарешті завжди виграє, якщо не зачепити шнур живлення: thedailywtf.com/Articles/My-Tales.aspx
Michael

22
Я не впевнений, який код повинен повернути в цьому випадку. Але я абсолютно впевнений , що ви не повинні ставити returnв finallyп.
jfs

325

APL (крім ВСІХ), можливість писати будь-яку програму лише в одному рядку.

наприклад , Гра життя Конвея в одному рядку в APL :

alt текст http://catpad.net/michael/APLLife.gif

Якщо ця лінія не є WTF, то нічого!

А ось відео


19
Я люблю APL. Ах, радощі витрачати цілий день на написання пів рядка коду! Перше, що я зроблю, коли отримаю клавіатуру, на якій я можу запрограмувати, які букви відображаються, - це знову познайомитися з APL.
Даніель К. Собрал

24
Схоже на мову для греків.
Есько

45
@Erik: Радості можна знайти в написанні коду, який стосується виключно того, що ви хочете, а не про те, як дістатися. Висловлення коду як єдиного виразу. Це як кінцевий ідеальний розріз катани. Звичайно, у реальній боротьбі я б швидше мав пістолет.
Даніель К. Собрал

7
@Daniel: Ви витрачаєте цілий день на написання рядка коду ... і цілий тиждень, щоб прочитати рядок коду. ;-)
Юрген А. Ерхард

93
APL було б дивним побачити у науково-фантастичному бойовику. Я можу собі уявити, як хтось сидить за трикольоровим терміналом, мармучучи: "Переформатуйте ракетний вектор ворога ... перенесіть ... пі рази логарифм ... оцініть - і - виконайте!" з подальшим вибухом та окликом.
Joey Adams

321

Для цього можна використовувати дивні шаблони C ++, найкраще продемонстровані "Багатовимірними аналоговими літералами", які використовують шаблони для обчислення площі "намальованих" фігур. Наступний код є дійсним C ++ для прямокутника 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) );

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

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


83
$[Змінна є самим злим з усіх.
Бред Гілберт

24
Однозначно оцінив би це, якби Perl 6 був чимось, на що я міг би кодувати, не перевіряючи perldoc perlvarкожні п'ять секунд (Хоча я зізнаюся, що половину часу я перевіряю це, думаючи, "я знаю, що існує спеціальна змінна, яка може це зробити для мене, я просто не пам'ятаю, яка з них ..." = P)
Кріс Луц

17
Проблема use English;полягає в тому, що це впливає на продуктивність RegExp. Я це не вигадую. perldoc.perl.org/English.html#PERFORMANCE
Дейв Вебб

13
@Dave: це не проблема через параметр -no_match_vars на сторінці, яку ви пов’язали. @Brad: $ [це так зло. Намір, що стоїть за цим, є злий, так, але він навіть не працює! @Artem: з perlvar "Ідентифікатори Perl, які починаються з цифр, контрольних символів або знаків пунктуації, звільнені від ефектів декларації пакета і завжди змушені бути в пакеті; вони також звільнені від суворої помилки" vars ". Тож це означає, що @ $ буде створено та призначено без помилок навіть за умови стриктури. Тьфу!
rjh

4
@Brian: Як ви пропонуєте вивчити синтаксис, коли в офіційній документації зазначено, що існують обставини, коли перекладач Perl евристично здогадується, що означає послідовність символів? Наприклад /$foo[bar]/, це [bar]частина класу символів чи підпис для масиву @foo? Греп перлдата за страхітливу відповідь.
j_random_hacker

289

PHP обробляє числові значення в рядках . Дивіться цю попередню відповідь на інше питання, щоб отримати детальну інформацію, але коротше:

"01a4" != "001a4"

Якщо у вас є два рядки, що містять різну кількість символів, їх не можна вважати рівними. Провідні нулі важливі, оскільки це рядки, а не числа.

"01e4" == "001e4"

PHP не любить рядки. Він шукає будь-яке виправдання, яке може знайти, щоб трактувати ваші значення як цифри. Трохи змініть шістнадцяткові символи в цих рядках і раптом PHP вирішить, що це вже не рядки, це числа в науковій нотації (PHP не байдуже, що ви використовували лапки), і вони еквівалентні тому, що провідні нулі ігноруються для чисел. Для посилення цього пункту ви побачите, що PHP також оцінює "01e4" == "10000"як істинне, оскільки це числа з еквівалентними значеннями. Це документоване поведінка, це просто не дуже розумно.


56
Просто використовуйте === і! ==. Який слід використовувати в будь-якому випадку, якщо не потрібно розв'язати типове порівняння
Дікам

14
@Dykam, якщо ви перейдете за посиланням на більш повну відповідь, ви побачите, що я звернувся до використання оператора ===.
Дан Дайер

18
Знову слабкий набір ударів!
gillonba

43
Я завжди знав, що PHP - це гріх. До цього часу я не усвідомлював, що це був непрощений гріх: D
Томас Едінг

2
Вони повинні технічним людям використовувати === у будь-якій книзі з програмування чи навчальному посібнику. Додана примітка: У погано написаному додатку PHP я зміг надати в якості свого пароля все, що було проаналізовано як однакове число.
Pepijn

282

Давайте проголосуємо за всі мови (наприклад, PL / I), які намагалися усунути зарезервовані слова.

Де б ви могли легально написати такі кумедні вирази, як:

IF IF THEN THEN = ELSE ELSE ELSE = THEN

( IF, THEN, ELSEЄ імена змінних)

або

IF IF THEN THEN ELSE ELSE

( IFє змінною, THENі ELSEце підпрограми)


1
@quark: це окрема відповідь на це! ;) ... (і так, ви можете програмувати з англійською мовою, просто розгорніть її як .ppt для інших розробників.;)
Макке

28
@RoadieRich одна група буйволів не є явно з Буффало, вони просто невідомий буйвол.
Юрген А. Ерхард

18
Джон, де в нього був Джеймс, мав кращий вплив на вчителя.
GameFreak

4
Днями я побачив деяких виробників знаків біля заводу морозива «Бен та Джеррі». Я критикував їхню роботу, я сказав їм, що між Бен-і, та і та і-джеррі не вистачає місця.
Том Гюллен

9
Можливо, це знадобиться для майбутніх тимчасових програм. ЯКЩО = ЗАРАЗ && ДЕ = ТУТ ТОЛЬКІ КОЛИ = ТОЛЬКО ЕЛЬШЕ ЗАРАЗ = ELSEWHERE
Келлі С. Французька

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 можна переплутати дію / час з оператором переключення. Ось приклад 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);
    }
}

9
Пристрій Даффа, ймовірно, є вагомою причиною того, що заява комутатора не має перерви за замовчуванням ;-) Однак я ще не бачив жодного іншого хорошого використання переплетених комутаторів та циклу - але, ймовірно, є такий. О, зачекайте, так, є ще одне використання: супроводи та прототрафи.
Фрунсі

16
@frunsi: "Пристрій Даффа, ймовірно, є вагомою причиною того, що оператор перемикання не має перерви за замовчуванням" - Завжди робіть загальний випадок за замовчуванням. Я б точно не сказав, що це звичайний випадок ..
BlueRaja - Danny Pflughoeft

6
@mcv, мабуть, найпростіше, якщо ви спробуєте прочитати його як код складання, тобто whileв кінці є (умовно) JMPповернення до do, що пояснює, чому ви можете пропустити doі все ще опинитися в циклі.
вд

14
Майте на увазі, що пристрій Даффа загалом створює код WORSE, ніж звичайний циклічний оператор для сучасних компіляторів, які знають, як (краще) розкручувати цикл, ніж ви можете зробити вручну.
Біллі ONeal

37
@frunsi: Сам Дафф, публікуючи це, стверджував щось подібне: "Це безумовно дає аргумент в дискусії про те, чи слід перемикатися за замовчуванням, але я не впевнений, аргумент" за "чи" проти ".
СФ.

204

Пропуск Algol по імені (проілюстровано за допомогою синтаксису 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]);
}

33
Якщо ви задумаєтесь, це насправді має певний кручений сенс
RCIX

90
Це кінцевий "пропуск шляхом посилання".
Дікам

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
Це насправді досить прямо: Ви генеруєте невеликий шматок коду (зазвичай його називають "громом", звідси мій каламбур вище), який обчислює адресу, отриману в результаті виразу, в даному випадку & a [i]. Вказівник на цю функцію передається на викликану функцію, яка потім використовує її для обчислення поточної адреси кожного разу, коли доступ до параметра.
Річард Пеннінгтон

189

На Python:

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

Не WTF, а корисна функція.


176
Бажаю, щоб у кожної іншої мови була така особливість
vava

32
Як і в майже кожній крутій функції Python, схоже, що Guido просто ALGOL-сидів синтаксис класної функції 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.
Baffe Boyois

189

На Java:

int[] numbers() {
  return null;
}

Можна записати так:

int numbers() [] {
  return null;
}

23
Оце Так! Я б хотів, щоб я міг літати на стіні, коли цей синтаксис масиву був розроблений!
Адам Пейнтер

29
Я ненавиджу це говорити, але WTF - це послідовне розширення системи типу C. Якби функціям C було дозволено повертати масиви, це виглядатиме так. Приємніше - це порушення послідовності, щоб зробити його більш читабельним. Так само, як "const char * var" vs "char const * var".
Гордон Вріглі

15
@Adam - Це насправді має сенс, якщо ви вважаєте, що оголошення змінної аналогічно дозволяє одночасно "int stuff []" і "int [] stuff". Вони просто дозволяють тим же правилам працювати для декларування методу.
Брендон Ярбро

2
@lImbus: Власне, const T*і T const*вони рівнозначні, це те, T* constщо обмежує покажчик. Також я ненавиджу sans шрифти.
Саймон Бучан

3
Адже numbers()[2]це юридична заява.
badp

184

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

COMEFROM є приблизно протилежною GOTO, оскільки він може приймати стан виконання з будь-якої довільної точки коду до оператора COMEFROM. Точка в коді, де відбувається передача стану, зазвичай задається як параметр COMEFROM. Будь передача відбудеться до або після інструкції у вказаній точці передачі, залежить від мови, що використовується. Залежно від мови, що використовується, декілька COMEFROM, що посилаються на одну і ту ж точку відправлення, можуть бути недійсними, бути недетермінованими, виконуватись з певним певним пріоритетом або навіть викликати паралельне або інше паралельне виконання, як це видно в Threaded Intercal. Простий приклад заяви "COMEFROM x" - це мітка x (яка не потребує фізичного розміщення в будь-якому місці біля відповідного COMEFROM), яка виступає як "дверна пастка". Коли виконання коду досягає мітки, контроль передається оператору, що слідує за COMEFROM. Ефект цього полягає насамперед у тому, щоб зробити налагодження (і зрозуміти потік управління програмою) надзвичайно важко, оскільки поблизу мітки немає вказівки на те, що управління таємничим чином перейде до іншої точки програми.


16
Досить зло - перетворює етикетки в GOTO. Схоже, мовні хакери благають ...
RCIX

114
Гаразд, але INTERCAL повинен бути смішним - це насправді не дивовижна "готча". Компілятор INTERCAL може насправді відмовитися від компіляції програми, якщо ви не використовуєте PLEASEмодифікатор досить часто!
Гроо

10
Звучить як AOP :)
akuhn

6
Що мене найбільше дивує, це те, що в аналізі системних вимог у "Світі комерційних TI" COMEFROM фактично використовуються в текстових файлах, що описують випадки використання. (серйозно: деякі аналітики тут затягнули корпоративну міграцію до OpenOffice замість MS Office, тому що перший не зміг належним чином посилатися на "comefrom" з необхідною деталізацією у посиланні)
jsbueno

5
Гроо: Гірше. Використовуйте PLEASE занадто часто, і вона відмовляється компілювати свою програму, оскільки ви налаштовані (C-INTERCAL вимагає від 33% до 66% заяв, щоб мати модифікатори PLEASE).
Ватін

160

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

f(1)

Компілятор передасть функцію адреси постійної 1 у постійному пулі. Якщо ви присвоїли значення параметру функції, ви змінили б значення (в даному випадку значення 1) глобально в програмі. Викликав пекель з головою.


124
О-о. Тоді 2+2 можна дорівнювати 5(для дуже великих значень, 2звичайно!).
Алок Сінгал

12
гм, яке значення 2 склало б "2 + 2" == "5"? Я не знаю, що будь-яке ціле значення 2 може прийняти, щоб це було правдою.
Аарон

36
@earlz: Я підозрюю, що це буде невід'ємною цінністю будь-якого бітного шаблону. З іншого боку, ви, ймовірно, могли встановити 5 до 4 таким чином (так 2+2би дорівнювали 5малі значення 5).
Девід Торнлі

18
Вибачте, Алок, але про це рано говорити FORTRAN. Це не буде правдою 2 + 2 = 5; це буде помилка синтаксису. Що буде правдою, так і є 2 + 2 .EQ. 5.
Девід Торнлі

3
У Haskell наступний фрагмент оцінює до 5: "нехай 2 + 2 = 5 в 2 + 2" :)
Тірпен

153

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


15
Це нормально, більшість кодів, пов'язаних із шаблонами, вже створюють безліч WTF у всьому світі.
Joris Timmermans

43
Ой приходь зараз. невизначена посилання на `std :: basic_ostream <char, std :: char_traits <char>> & std :: оператор << <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);
}

Як чорт це однозначно компілює !?
Граф

13
+1 Ідентифікатори тегів для переліків та структур є найбільш заплутаною частиною C imho. Мало хто розуміє, чому ідіома для введення вказівника на структуру виглядає так, як це робиться.
Тадеуш А. Кадлубовський

11
Він компілюється тому, що кожен з цих я має однозначну область імен через контекст.
Ендрю Макгрегор

149

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

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

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

редагувати 2: деякі люди, які надають коментарі, здаються, що це ненависна особливість, або, на мою думку, робить Python поганою мовою. Знову ж таки, неправда. Хоча мені це все не подобається, це вже не в питанні. Питання полягає у найдивнішій мовній особливості, і я думаю, що це дивно, через те, що він використовує щось дуже, дуже мало (але> 0) мов.


63
якщо це заважає вашій продуктивності, то ваш
непітонський

27
Якою мовою ви користувалися до Python? Як вам вдалося працювати з іншими людьми і не відступати від цієї мови? Як міг хтось миритися з невідступним кодом будь-якою мовою? Ви працювали в кімнаті, повною геніями, яким не потрібні візуальні підказки у вихідному коді?
С.Лотт

53
+1 Не можу погодитись більше, якщо мій редактор (Emacs) не може автоматично відрізати мій код на основі чогось чіткого (наприклад, дужки / початок, кінець / ви його називаєте), це дуже нерозумно. Насправді, будь-який рефакторинг, який ви виконували б на "більшій" функції, може бути дуже поганим досвідом.
Дмитро

83
Ось угода - будь-якою іншою мовою я можу виділити блок коду і правильно його відрізати будь-яким редактором. Але оскільки пробіл IS за визначенням належного відступу, ви втрачаєте цю здатність у Python. Так що складніше переміщувати код або рефакторити речі. А для людини, яка стверджує, що ОП є "першою особою, яка заявила, що це була проблема", мені довелося деякий час підтримувати код python, і я саме зараз буду використовувати будь-яку мову через python.
Kendall Helmstetter Gelner

38
Я не проти пробілів у Python. WTF полягає в тому, що він не застосовується послідовно. Ви можете змішувати рівні відступів і вкладки, якщо вони відповідають їхнім побратимам. Отже, перший рівень відступу може бути одним пробілом, а другий - двома таблицями TAB, і це не синтаксична помилка.
ieure

138

Я трохи боровся з цього приводу:

1;

У перлі, модулі потрібно повернути щось справжнє .


29
Деякі модулі можуть повертати значення на основі операцій виконання. Якщо ви завжди повертаєте істину, ви все одно не повинні бути недоброзичливими щодо цього: returnvalues.useperl.at
Анонім

8
Якщо моя пам'ять Perl служить мені правильно, повернення істини з модуля вказує на те, що модуль успішно завантажений. Повернення помилкового значення означало, що щось пішло не так і заважало програмі запускатись (якщо її не застало).
Баррі Браун

Це також дійсне твердження C, тільки нічого не повертається.
sigjuice

24
Марк Домінус писав: "Я дуже рідко використовую, 'Cogito ergo sum';що, як всі знають, є само собою очевидним у всіх можливих всесвітах. Це забезпечує максимальну мобільність".
Грег Бекон

PHP <?=1;?>повертає 1. <?=true;?>повертає 1. <?=false;?>повертає null.
Талві Ватія

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

Тому що стирчить! перед вашим умовним чином занадто складно!


47
Вони повинні були зробити це " Whileі Whend", оскільки є деякі люди, які вимовляють слово "в той час" з беззвучним лабіалізованим велярним наближенням. І звичайно, це вибудовує приємніше, і код, який вибудовує, приємно.
dreamlax

43
Чому ти так поводишся?
Ерік Форбс

48
Ого. Мені стає ностальгічно, коли я думаю про це. Перший раз, коли я коли-небудь користувався VB, повернувся ще як 9-річний. Я зі Швеції, і не дуже добре володів англійською мовою. Тепер є шведське слово під назвою "vänd", яке в основному означає "повернути назад", яке вимовляється аналогічно "wend". Через це я подумав, що це має багато сенсу ... :)
Еміль Н

61
! не в VB, це "Ні". Або це? Так, не є !, але ні.
бріанарі

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


41
Я використовую Haskell для цього матеріалу.
Томас Едінг

8
Калькулятор Google?
igul222

7
Я почав сам користуватися Python, і Google калькулятор приємний, якщо ви в Інтернеті. Але я раніше користувався bcцим і хотів писати про себе bcу своєму пості через великі цитати зі сторінки man.
Алок Сінгал

6
@Brian, тоді вам сподобається: echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc(хоча ви, можливо, це вже знаєте).
Алок Сінгал

2
Я використовую irb (інтерактивну оболонку Ruby). Але назад у той день я завжди досягав dc - як bc, але використовую зворотний лак. Геектастик!
трагомасхалос

134

Мені завжди було цікаво, чому найпростіша програма:

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

Тоді як це могло бути:

print "Hello World!"

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


34
У деяких мовах "Привіт, світ!" є дійсною програмою.
Девід Торнлі

31
@SoMoS: у більшості динамічних мов, таких як Python, Ruby або Perl, надрукуйте "Hello World!" або деякі незначні зміни (наприклад, замість друку) є дійсною і повною програмою.
Дейв Кірбі

36
@Loadmaster: сенс полягав у тому, що "весь код належить до класу" або "весь код належить функції" є непотрібними обмеженнями
Джиммі

19
Тільки тому, що мова примушує використовувати об'єкти, не означає, що вона використовується для правильного об'єктно-орієнтованого програмування. Це цілком можливо програмувати процедурно на Java або C #. Ось для чого призначені статичні методи.
jdmichal

68
Я люблю людей, які думають, що ООП означає, що все повинно бути об’єктом.
Tor Valamo

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?


6
Ось чому ви повинні використовувати ===замість цього.
Гумбо

10
Це корисно btw, якщо у вас є функція, яка повертає число, і ви хочете повернути деякі додаткові метадані з ним, ви можете повернути [номер], додавши деякі додаткові поля. Простий код ніколи не дізнається, що це не реальна кількість, а інший код може отримати необхідні метадані.
Андрій Щекін

36
@Andrey за винятком того, що якщо мені коли-небудь доведеться підтримувати код, який робить те, що ви пропонуєте, я дуже скоро бажаю смерті його автору.
Бретон

@Andrey, це чудова ідея! Ви також можете використовувати Number(n)щось подібне. На жаль, в обох наших рішеннях ===перерви = (.
Xavi

5
+1: Я вважав себе знаючим програмістом js, і про це ніколи не знав: D
Томас Едінг

126

Моя найбільша ненависна особливість - це будь-який синтаксис файлу конфігурації, який включає умовну логіку. Така річ буває в світі Java (мураш, Мавен та ін. Ви знаєте, хто ви!).

Ви просто закінчите програмування на мові змінного струму **, з обмеженою налагодженням та обмеженою підтримкою редактора.

Якщо вам потрібна логіка у вашій конфігурації, "Pythonic" підхід кодування конфігурації реальною мовою набагато краще.


24
Tcl переосмислив це задовго до того, як народився Python, а Лісп винайшов його до цього. Тож давайте не будемо називати це пітонічним, давайте назвати його Emacs-ish.
slebetman

46
Давайте просто назвемо це правильно.
mletterle

30
AMEN. Якщо ваша конфігурація чи мова збірки завершено, ви робите це неправильно. Я дивлюся на вас CMake / autotools.
Джозеф Гарвін

16
Саме для цього і був розроблений Lua, спочатку
Cogwheel

1
Що ж, якщо ваш код у Python, то, якщо ваш конфігураційний файл бути файлом Python, це чудова ідея, тому що ви просто імпортуєте файл і читаєте атрибути модуля. І ви отримуєте 100% повну потужність Python у своєму конфігураційному файлі.
асмеурер

113

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

# BLOAT {bloatsize}

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


9
Ха-ха юк. Я чув про розробників, які навмисно сповільнюють деякі операції (наприклад, пошук), оскільки це допомагає людям вірити, що це дійсно щось робить. Думаю, подібна річ.
Давид

42
Це нагадує мені те, що я читав недавно. Вони тестували FPS і вирішили збільшити кількість балів, які потрапили погані хлопці. Потім вони запитали тестувальників, як вони AI, і вони поклялися, що це набагато розумніше. Але ШІ не змінився, а лише точки удару. Люди мають певну розповідь про світ у своїх головах, і якщо ви розумієте та відповідаєте їхнім очікуванням, вони просто припускають, що це підтверджує їх розповідь.
Nate CK

5
Я використовував багато додаткових уповільнень у своїх програмах, щоб зробити їх схожими на щось складне. Ще в початковій школі, тобто.
Матті Вірккунен

3
Ще в школі у нас було 80286 машин, і я насправді повинен був написати деякі підпрограми виводу екрану в зборі, щоб отримати розумну швидкість (тобто не повзати).
berkus

7
@Nate CK, якщо AI живе досить довго, щоб показати свій AI, він насправді може бути розумнішим, тоді як раніше він, можливо, загинув занадто швидко, щоб довести це.
zzzzBov
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.