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

Из эмпирического тестирования кажется, что max() и min() в списке вернут первое в списке, которое соответствует max() / min() в случае связи:

>>> test = [(1, "a"), (1, "b"), (2, "c"), (2, "d")]
>>> max(test, key=lambda x: x[0])
(2, 'c')
>>> test = [(1, "a"), (1, "b"), (2, "d"), (2, "c")]
>>> max(test, key=lambda x: x[0])
(2, 'd')
>>> min(test, key=lambda x: x[0])
(1, 'a')
>>> test = [(1, "b"), (1, "a"), (2, "d"), (2, "c")]
>>> min(test, key=lambda x: x[0])
(1, 'b')

И Отличное слежение Джереми подтверждает, что это действительно так.

975
задан 22 revs, 8 users 38% 26 September 2011 в 15:40
поделиться

285 ответов

Даты JavaScript полны WTF.

var d = new Date("1/1/2001");

var wtfyear = d.getYear(); // 101 (the year - 1900)
// to get the *actual* year, use d.getFullYear()

var wtfmonth = d.getMonth(); // 0
// months are 0-based!
25
ответ дан 22 November 2019 в 20:53
поделиться

Одним из моих любимых в С++ является "публичный абстрактный деструктор поточного типа":

class AbstractBase {
public:
    virtual ~AbstractBase() = 0 {}; // PACID!

    virtual void someFunc() = 0;
    virtual void anotherFunc() = 0;
};

Я украл его у Скотта Мейерса в Effective C++. Выглядит немного странно, когда я вижу метод, который одновременно является чисто виртуальным (что обычно означает "абстрактным") и реализован inline, но это лучший и самый лаконичный способ, который я нашел, чтобы обеспечить полиморфное разрушение объекта.

27
ответ дан 22 November 2019 в 20:53
поделиться

В PHP строка так же хороша, как указатель на функцию:

$x = "foo";
function foo(){ echo "wtf"; }
$x(); # "wtf"

К сожалению, это не работает:

"foo"();
29
ответ дан 22 November 2019 в 20:53
поделиться

На мой взгляд, довольно странно быть способным отбрасывать вне диапазона входные данные в перечисления на Си#. Представьте себе это enum:

enum Colour
{
    Red = 1,
    Green = 2,
    Blue = 3
}

Теперь, если вы напишете:

Colour eco;
eco = (Colour)17;

Компилятор думает, что это нормально. И время исполнения тоже.

Смотрите здесь подробнее.

21
ответ дан 22 November 2019 в 20:53
поделиться

Хорошо, так как вопрос будет в прерывистом режиме, я присоединюсь к "fun"

Go ( также известному как Issue9 ) использованию верхнего регистра для видимости:

  • Если вы назовёте что-то с заглавными буквами, то оно будет иметь публичный доступ.

  • Если вы используете нижний регистр, то он будет защищен:

Видимый вне пакета:

func Print(v ...) { 
}

Невидимый вне пакета

func print( v ... ) {
}

Вы можете найти больше в этом оригинальном ответе.

19
ответ дан 22 November 2019 в 20:53
поделиться

Вот хороший набор странных возможностей C: http://www.steike.com/code/useless/evil-c/

18
ответ дан 22 November 2019 в 20:53
поделиться

Примерно 20 лет назад, когда я в последний раз работал в MUMPS, реализации имели некоторые любопытные ограничения. В то время как хосты MUMPS становились всё более популярными, MUMPS традиционно был языком самохостинга: компьютерный язык, операционная система и база данных в одном пакете.

MUMPS в основном был связан со своей базой данных. По сути, огромная многомерная хэш-таблица, поддерживаемая деревом B*, что делало доступ к ней очень быстрым. Между языком и БД тоже не было никакого барьера: если вы хотели, чтобы что-то там хранилось, вы просто префиксовали переменную с символом, указывающим на то, что она должна сохраняться в бэк-магазине.

С другой стороны, файловая система практически не существовала, а поддержка ее была еще меньше. Единственное, что можно было сделать, это загрузить программу в память из файла и отправить все, что было в памяти, обратно в файл. И лучше было очистить буфер перед загрузкой, иначе он смешивался бы с тем, что было там первым.

Так что, учитывая его самохостинговую природу и чрезвычайно враждебную файловую систему, можно было бы поинтересоваться, как редактировались эти программы. Редакторы, на самом деле, были написаны в самом MUMPS -- так как же редактор мог хранить программу в памяти, не записывая ее поверх себя?

Ну, хитрость заключалась в возможности выполнить содержимое переменной в виде исходного кода. Затем редактор загружал себя в переменные, выполнял себя в них, очищал память, а затем загружал, сохранял и редактировал файлы в памяти, все время выполняясь из переменных.

Добавьте к этому то, что все команды можно было бы сократить до первых букв (за исключением команд Z, сокращенных до двух букв, которые в основном обрабатывали файловую систему), и курьезы, такие как тот факт, что IF (I) установил переменную, с которой затем посоветовался ELSE (E) -- и которая, конечно же, может быть переопределена любым вмешательством I, или самой программой. Если подумать, то я думаю, что весь язык был WTF. И, тем не менее, у него было странное притяжение.

27
ответ дан 22 November 2019 в 20:53
поделиться

Удивительно, что никто не упомянул REALLY уродливую реализацию коммутационного кейса на большинстве С-подобных языков

switch (someInt) {
    case 1:
    case 2: System.out.println("Forgot a break, idiot!");
    case 3: System.out.println("Now you're doing the wrong thing and maybe need hours to find the missing break muahahahaha");
            break;
    default: System.out.println("This should never happen -,-");        
}

Хорошо, что более новые языки правильно его реализовали.

20
ответ дан 22 November 2019 в 20:53
поделиться

Как энтузиаст NHibernate, я был в восторге, когда услышал о том, что становится из Smalltalk... например,

a become: b

буквально превращает объект в b, что делает тривиальным написание ленивых инициализированных прокси, потому что все ссылки на завещание теперь ссылаются на b. Довольно аккуратно!

Я думаю, что это квалифицируется как странная особенность языка в том, что ни один другой язык не обладает такой способностью к моим знаниям.

23
ответ дан 22 November 2019 в 20:53
поделиться

Другие странные вещи:

В C++ переопределение виртуального метода скрывает все остальные перегрузки этого метода. В Java этого не происходит. Это очень раздражает. Пример: http://codepad.org/uhvl1nJp

В C++ если базовый класс имеет public виртуальный метод foo(), а подкласс имеет private метод foo(), то этот private метод переопределяет другой! Таким образом, можно вызвать метод private вне класса, просто приведя указатель объекта подкласса к указателю объекта суперкласса. Этого не должно быть: это нарушение инкапсуляции. Новый метод не должен рассматриваться как переопределение старого. Пример: http://codepad.org/LUGSNPdh

В PHP можно определить функции, принимающие типизированные параметры (например, объекты, являющиеся подклассами определенного интерфейса/класса). Забавно, что таким образом нельзя использовать NULL в качестве фактического значения параметра в данном случае. Пример: http://codepad.org/FphVRZ3S

28
ответ дан 22 November 2019 в 20:53
поделиться

Scanner предназначен для синтаксического анализа текстовых данных - метод nextByte () ожидает, что входные данные будут состоять из цифр (возможно, перед которыми будет стоять знак).

Возможно, вы хотите использовать FileReader , если вы действительно читаете текстовые данные, или FileInputStream , если это двоичные данные. Или FileInputStream , заключенный в InputStreamReader , если вы читаете текст с определенной кодировкой символов (к сожалению, FileReader не позволяет указать кодировку, но использует кодировку платформы по умолчанию неявно, что часто нехорошо).

-121--4667852-

Это ошибка:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42655

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

template<typename T>
void
unused(T const &) {
  /* Do nothing. */
}

int main() {
  volatile bool x = false;
  bool avoidGCC42655 = !x; // type of "!x" is bool
  unused(avoidGCC42655);
}
-121--4349707-

В Ruby 0 вычисляется как true в условных выражениях.

27
ответ дан 22 November 2019 в 20:53
поделиться

Вот что-то, что работает для меня:

<ContentControl Content="{Binding SomeBool}">
  <ContentControl.Resources>
    <DataTemplate x:Key="PinkTemplate">
      <TextBlock Text="{Binding}" Background="Pink" />
    </DataTemplate>
    <DataTemplate x:Key="LimeTemplate">
      <TextBlock Text="{Binding}" Background="Lime" />
    </DataTemplate>
  </ContentControl.Resources>
  <ContentControl.ContentTemplate>
    <DataTemplate>
      <ContentControl Name="cc"
                      Content="{Binding}"
                      ContentTemplate="{StaticResource PinkTemplate}" />
      <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding}" Value="True">
          <Setter TargetName="cc" 
                  Property="ContentTemplate"
                  Value="{StaticResource LimeTemplate}" />
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </ContentControl.ContentTemplate>
</ContentControl>

Обратите внимание, что мой DataTemplate является еще одним ContentControl, который позволяет My DataTemplate .Triggers для работы на ContentTemplate для этого (вложенного) ContentControl.

-121--3787322-

В JavaScript результатом способа может зависеть от метательных скобок в стиле. Это стиль , где скобки помещаются сразу после подписи метода и после оператора возврата:

var foo = function() {
  return {
    key: 'value'
  };
}

foo() // returns an object here

Теперь, если я отформатирую этот код в стиль , где брекеты всегда размещаются на новой строке, результат другой:

var foo = function()
{
  return
  {
    key: 'value'
  };
}

foo() // returns undefined here

Как прийти? В JavaScript язык помещает автоматически запястья в конце каждой строки, если вы не будете делать это самостоятельно. Итак, что на самом деле произошло в последнем фрагменте кода, было это:

var foo = function()
{
  return; // here's actually a semicolon, automatically set by JavaScript!
  {
    key: 'value'
  };
}

так, если вы позвоните foo () , первое утверждение в методе будет возврата, которое вернется undefined и не будет выполнять другие следующие утверждения.

29
ответ дан 22 November 2019 в 20:53
поделиться

В C-подобных языках (включая сам C) вы можете использовать оператор «спускается к»:

for (x = 20; x --> 0;) {
    print x;
}

Это напечатает числа от 19 на 0.

27
ответ дан 22 November 2019 в 20:53
поделиться

Абсолютно худший WTF должен быть ALTERED GOTO Кобола.

Синтаксис довольно прост: «ALTER label1 TO GOTO label2», но результаты отладки спагетти времени выполнения ошеломляют.

27
ответ дан 22 November 2019 в 20:53
поделиться

Perl:

Можно написать программу, состоящую полностью из знаков препинания.

Как это вообще работает?!

20
ответ дан 22 November 2019 в 20:53
поделиться

Это один из моих любимых вариантов, вы можете выполнять печать на Java без main ().

Это будет скомпилировано и запущено с выдачей println, но также будет исключение (java.lang.NoSuchMethodError: main)

class Test {
    static {
        System.out.println("I'm printing in Java without main()");
    }
}
17
ответ дан 22 November 2019 в 20:53
поделиться

Мне нравится вводить восьмеричные значения в C:

int values[8] = { 123, 154, 103, 310, 046, 806, 002, 970 };
18
ответ дан 22 November 2019 в 20:53
поделиться

Я написал язык программирования для клиента (используемый для экспериментального управления пользовательским оборудованием) с некоторыми пользовательскими типами (Curl, Circuit, ....), каждый из которых имеет только 2 значения. Они неявно конвертируются в булевы, но (по желанию клиента) точное булевое значение константы такого типа может быть изменено во время исполнения.

Например: Тип Curl имеет 2 возможных значения: CW и CCW (по и против часовой стрелки). Во время исполнения можно изменять булевое значение простым оператором присваивания:

ccw := true

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

.
15
ответ дан 22 November 2019 в 20:53
поделиться

ActionScript 3:

Когда интерфейс объекта используется, компилятор не распознает методы, унаследованные от Object, следовательно:

IInterface interface = getInterface();
interface.toString();

дает ошибку компиляции. Обходным путем является преобразование в операторы Object

Object(interface).toString();

PHP:

. и +. Этому есть разумное объяснение, но всё же "a" + "5" = 5 кажется неловким.

Java (и любая реализация IEEE754):

System.out.println(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1);

Выводит 0.99999999999999

15
ответ дан 22 November 2019 в 20:53
поделиться

Почему C# List.AddRange() не позволяет мне добавлять элементы подтипа T? List.Add() does!
Все, что потребуется, это ONE дополнительная строчка кода со стороны Microsoft:

public void AddRange<S>(
    IEnumerable<S> collection
) where S : T
16
ответ дан 22 November 2019 в 20:53
поделиться

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

.
12
ответ дан 22 November 2019 в 20:53
поделиться

В JavaScript (и Java, я думаю) вы можете избежать таких забавных символов:

var mystring = "hello \"world\"";

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

var mystring = "hello, \nworld";

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

var mystring = "hello, \
world";
12
ответ дан 22 November 2019 в 20:53
поделиться

В Python:

>>> a[0] = "hello"
NameError: name 'a' is not defined
>>> a[0:] = "hello"
NameError: name 'a' is not defined
>>> a = []
>>> a[0] = "hello"
IndexError: list assignment index out of range
>>> a[0:] = "hello"
>>> a
['h', 'e', 'l', 'l', 'o']

Эти назначения срезов также дают те же результаты:

a[:] = "hello"
a[42:] = "hello"
a[:33] = "hello"
12
ответ дан 22 November 2019 в 20:53
поделиться

Вызовы операторов в стиле Perl.

В начале было

print "foo", "bar", "baz"; # to stdout
print STDERR "foo", "bar", "baz";

Обратите внимание на показное отсутствие запятой, чтобы вы знали, что это файловый менеджер для печати, а не файловый менеджер для печати в строковом виде. Это грязный взлом.

Обновление языка происходит, они делают правильные OO-файлы и превращают x FOO y, z, abc в FOO->x(y, z, abc). Как мило. Тот же самый оператор печати фактически запускает

STDERR->print("foo", "bar", "baz");

В основном вы замечаете это, когда пропускаете запятую, или пытаетесь запустить что-то вроде hashof $a, $b, $c (вызов подпрограмм без скобок) и забываете импортировать функцию hashof в ваше пространство имен из пакета утилит, и вы получаете странное сообщение об ошибке "Can't call method 'hashof' through package 'contents of string $a"".

13
ответ дан 22 November 2019 в 20:53
поделиться
[

] В C# это должно, по крайней мере, выдавать предупреждение компилятору, но не:[

]. [
public int Something
{
    get { return Something; }
    set { Something = value; }
}
] [

] Когда вызывается, это приводит к отказу вашего приложения, и вы не получаете хорошую трассировку стека, так как это StackOverflowException. [

]
16
ответ дан 22 November 2019 в 20:53
поделиться
[

] Когда я учился в колледже, я немного поработал на языке, который называется СНОБОЛ. Весь язык, хоть и крутой, но один большой WTF. [

] [

] У него самый странный синтаксис, который я когда-либо видел. Вместо GoTo вы используете :(label). И кому нужно, если у вас :S(label) (goto label on success/true) и :F(label) (goto label on failure/false) и вы используете эти функции в строке, проверяя какое-то условие или читая файл. Итак, утверждение:[

] [
H = INPUT :F(end)
] [

] прочитает следующую строку из файла или консоли и перейдет к метке "конец", если чтение прошло неудачно (потому что EOF достигнуто или по любой другой причине). [

] [

] Тогда есть оператор знака $. Он будет использовать значение в переменной в качестве имени переменной. Итак: [

] [
ANIMAL = 'DOG'
DOG = 'BARK'
output = $ANIMAL
] [

] поставит значение "BARK" на консоли. И потому, что это не достаточно странно: [

] [
$DOG = 'SOUND'
] [

] создаст переменную с именем BARK (см. значение, присвоенное DOG выше) и даст ей значение 'SOUND'. [

] [

] Чем больше ты на него смотришь, тем хуже становится. Лучшее утверждение, которое я когда-либо находил о SNOBOL (из текста ссылки [] []) - "сила языка и его довольно идиоматические возможности управления потоком делают код SNOBOL4 практически невозможным для чтения и понимания после его написания". "[

]
15
ответ дан 22 November 2019 в 20:53
поделиться

Модификаторы доступа Java для меня - это недавняя WTF (как мне пришлось немного узнать).

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

Но я могу определить атрибуты и методы, которые видны каждому классу в пакете, но не подклассам вне пакета.

Неважно, как сильно я об этом думаю, я все равно не вижу логики. Переключите модификаторы доступа и заставьте protected действовать так, как это работает в C++, и сохраните закрытый модификатор пакета таким, какой он есть, и это будет иметь смысл. Теперь нет.

9
ответ дан 22 November 2019 в 20:53
поделиться

В PHP "true", "false" и "null" являются константами, которые обычно не могут быть переопределены. Однако, с введением пространств имен в PHP >=5.3, теперь можно переопределить эти константы в любом пространстве имен, кроме глобального. Что может привести к следующему поведению :

namespace {
    define('test\true', 42);
    define('test\false', 42);
    define('test\null', 42);
}

namespace test {
    var_dump(true === false && false === null); // is (bool) true
}

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

namespace test {
    var_dump(\true === \false); // is (bool) false
}
15
ответ дан 22 November 2019 в 20:53
поделиться

В PHP Струны буквы не могут быть использованы как в C, вам необходимо использовать ord () и CHR () , чтобы преобразовать из Номер для Char и Vica Versa: «A»! = 97 , но ord («A») == 97 .

Хотя, есть одно исключение:

for ($i = 'a'; $i < 'z'; $i++) {
    print "$i ";
}

будет печатать буквы A к Y. Также как вы ожидаете, как если бы это был C стиль данных стиля.

Однако, если состояние испытания изменено на <= , он не будет распечатать a to z, как вы думаете, но a to yz! (Всего напечатано 676 предметов)

Также, если вы измените «Z» на «AA», который вышел на улицу после «Z» в списке 676 элементов, и измените условия теста на < снова, вы снова Увидим только «A», напечатанный! Не до Z, как вы ожидаете.

И если вы измените инкремент на $ i + = 2 , он снова будет печатать только «A»! Только способ сделать это использовать $ i ++ , $ i ++ в последовательности, и теперь он работает как ожидаемый.

Тем не менее, это хороший способ в PHP для выходных комбинаций букв A-Z, хотя его очень трудно использовать его.

11
ответ дан 22 November 2019 в 20:53
поделиться

String Math в Perl довольно странно.

$ perl -E '$string = "a"; $string++; say $string'
b

$ perl -E '$string = "abc"; $string++; say $string'
abd

$ perl -E '$string = "money"; $string++; say $string'
monez

$ perl -E '$string = "money"; $string--; say $string'
-1
11
ответ дан 22 November 2019 в 20:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: