Из эмпирического тестирования кажется, что 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')
И Отличное слежение Джереми подтверждает, что это действительно так.
Даты 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!
Одним из моих любимых в С++ является "публичный абстрактный деструктор поточного типа":
class AbstractBase {
public:
virtual ~AbstractBase() = 0 {}; // PACID!
virtual void someFunc() = 0;
virtual void anotherFunc() = 0;
};
Я украл его у Скотта Мейерса в Effective C++. Выглядит немного странно, когда я вижу метод, который одновременно является чисто виртуальным (что обычно означает "абстрактным") и реализован inline, но это лучший и самый лаконичный способ, который я нашел, чтобы обеспечить полиморфное разрушение объекта.
В PHP строка так же хороша, как указатель на функцию:
$x = "foo";
function foo(){ echo "wtf"; }
$x(); # "wtf"
К сожалению, это не работает:
"foo"();
На мой взгляд, довольно странно быть способным отбрасывать вне диапазона входные данные в перечисления на Си#. Представьте себе это enum:
enum Colour
{
Red = 1,
Green = 2,
Blue = 3
}
Теперь, если вы напишете:
Colour eco;
eco = (Colour)17;
Компилятор думает, что это нормально. И время исполнения тоже.
Смотрите здесь подробнее.
Хорошо, так как вопрос будет в прерывистом режиме, я присоединюсь к "fun"
Go ( также известному как Issue9 ) использованию верхнего регистра для видимости:
Если вы назовёте что-то с заглавными буквами, то оно будет иметь публичный доступ.
Если вы используете нижний регистр, то он будет защищен:
Видимый вне пакета:
func Print(v ...) {
}
Невидимый вне пакета
func print( v ... ) {
}
Вы можете найти больше в этом оригинальном ответе.
Вот хороший набор странных возможностей C: http://www.steike.com/code/useless/evil-c/
Примерно 20 лет назад, когда я в последний раз работал в MUMPS, реализации имели некоторые любопытные ограничения. В то время как хосты MUMPS становились всё более популярными, MUMPS традиционно был языком самохостинга: компьютерный язык, операционная система и база данных в одном пакете.
MUMPS в основном был связан со своей базой данных. По сути, огромная многомерная хэш-таблица, поддерживаемая деревом B*, что делало доступ к ней очень быстрым. Между языком и БД тоже не было никакого барьера: если вы хотели, чтобы что-то там хранилось, вы просто префиксовали переменную с символом, указывающим на то, что она должна сохраняться в бэк-магазине.
С другой стороны, файловая система практически не существовала, а поддержка ее была еще меньше. Единственное, что можно было сделать, это загрузить программу в память из файла и отправить все, что было в памяти, обратно в файл. И лучше было очистить буфер перед загрузкой, иначе он смешивался бы с тем, что было там первым.
Так что, учитывая его самохостинговую природу и чрезвычайно враждебную файловую систему, можно было бы поинтересоваться, как редактировались эти программы. Редакторы, на самом деле, были написаны в самом MUMPS -- так как же редактор мог хранить программу в памяти, не записывая ее поверх себя?
Ну, хитрость заключалась в возможности выполнить содержимое переменной в виде исходного кода. Затем редактор загружал себя в переменные, выполнял себя в них, очищал память, а затем загружал, сохранял и редактировал файлы в памяти, все время выполняясь из переменных.
Добавьте к этому то, что все команды можно было бы сократить до первых букв (за исключением команд Z, сокращенных до двух букв, которые в основном обрабатывали файловую систему), и курьезы, такие как тот факт, что IF
(I
) установил переменную, с которой затем посоветовался ELSE
(E
) -- и которая, конечно же, может быть переопределена любым вмешательством I
, или самой программой. Если подумать, то я думаю, что весь язык был WTF. И, тем не менее, у него было странное притяжение.
Удивительно, что никто не упомянул 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 -,-");
}
Хорошо, что более новые языки правильно его реализовали.
Как энтузиаст NHibernate, я был в восторге, когда услышал о том, что становится
из Smalltalk... например,
a become: b
буквально превращает объект в b, что делает тривиальным написание ленивых инициализированных прокси, потому что все ссылки на завещание теперь ссылаются на b. Довольно аккуратно!
Я думаю, что это квалифицируется как странная особенность языка в том, что ни один другой язык не обладает такой способностью к моим знаниям.
Другие странные вещи:
В C++ переопределение виртуального метода скрывает все остальные перегрузки этого метода. В Java этого не происходит. Это очень раздражает. Пример: http://codepad.org/uhvl1nJp
В C++ если базовый класс имеет public виртуальный метод foo(), а подкласс имеет private метод foo(), то этот private метод переопределяет другой! Таким образом, можно вызвать метод private вне класса, просто приведя указатель объекта подкласса к указателю объекта суперкласса. Этого не должно быть: это нарушение инкапсуляции. Новый метод не должен рассматриваться как переопределение старого. Пример: http://codepad.org/LUGSNPdh
В PHP можно определить функции, принимающие типизированные параметры (например, объекты, являющиеся подклассами определенного интерфейса/класса). Забавно, что таким образом нельзя использовать NULL в качестве фактического значения параметра в данном случае. Пример: http://codepad.org/FphVRZ3S
Scanner предназначен для синтаксического анализа текстовых данных - метод nextByte ()
ожидает, что входные данные будут состоять из цифр (возможно, перед которыми будет стоять знак).
Возможно, вы хотите использовать FileReader
, если вы действительно читаете текстовые данные, или FileInputStream
, если это двоичные данные. Или FileInputStream
, заключенный в InputStreamReader
, если вы читаете текст с определенной кодировкой символов (к сожалению, FileReader
не позволяет указать кодировку, но использует кодировку платформы по умолчанию неявно, что часто нехорошо).
Это ошибка:
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 в условных выражениях.
Вот что-то, что работает для меня:
<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
и не будет выполнять другие следующие утверждения.
В C-подобных языках (включая сам C) вы можете использовать оператор «спускается к»:
for (x = 20; x --> 0;) {
print x;
}
Это напечатает числа от 19 на 0.
Абсолютно худший WTF должен быть ALTERED GOTO Кобола.
Синтаксис довольно прост: «ALTER label1 TO GOTO label2», но результаты отладки спагетти времени выполнения ошеломляют.
Это один из моих любимых вариантов, вы можете выполнять печать на Java без main ().
Это будет скомпилировано и запущено с выдачей println, но также будет исключение (java.lang.NoSuchMethodError: main)
class Test {
static {
System.out.println("I'm printing in Java without main()");
}
}
Мне нравится вводить восьмеричные значения в C:
int values[8] = { 123, 154, 103, 310, 046, 806, 002, 970 };
Я написал язык программирования для клиента (используемый для экспериментального управления пользовательским оборудованием) с некоторыми пользовательскими типами (Curl, Circuit, ....), каждый из которых имеет только 2 значения. Они неявно конвертируются в булевы, но (по желанию клиента) точное булевое значение константы такого типа может быть изменено во время исполнения.
Например: Тип Curl имеет 2 возможных значения: CW и CCW (по и против часовой стрелки). Во время исполнения можно изменять булевое значение простым оператором присваивания:
ccw := true
Таким образом, можно изменять булевое значение всех значений этих типов.
.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
Почему C# List
Все, что потребуется, это ONE дополнительная строчка кода со стороны Microsoft:
public void AddRange<S>(
IEnumerable<S> collection
) where S : T
Больше возможностей платформы, чем возможностей языка: на iPhone создайте бесконечный цикл с несколькими вычислениями внутри и запустите свою программу. Телефон нагреется, и Вы сможете использовать его как ручное подогревание, когда на улице будет холодно.
.В JavaScript (и Java, я думаю) вы можете избежать таких забавных символов:
var mystring = "hello \"world\"";
Если вы хотите поместить возврат каретки в строку, это невозможно. Вы должны использовать \n так:
var mystring = "hello, \nworld";
Это все нормально и ожидаемо - для языка программирования в любом случае. Странно то, что вы также можете экранировать реальный возврат каретки следующим образом:
var mystring = "hello, \
world";
В 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"
Вызовы операторов в стиле 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
"".
] В C# это должно, по крайней мере, выдавать предупреждение компилятору, но не:[
]. [public int Something
{
get { return Something; }
set { Something = value; }
}
]
[] Когда вызывается, это приводит к отказу вашего приложения, и вы не получаете хорошую трассировку стека, так как это StackOverflowException. [
]] Когда я учился в колледже, я немного поработал на языке, который называется СНОБОЛ. Весь язык, хоть и крутой, но один большой 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 практически невозможным для чтения и понимания после его написания". "[
]Модификаторы доступа Java для меня - это недавняя WTF (как мне пришлось немного узнать).
Очевидно, что пакеты более интимны, чем иерархии классов. Я не могу определить методы и атрибуты, которые видны подклассам, но не другим классам в пакете. И зачем мне делиться внутренностями класса с другими классами?
Но я могу определить атрибуты и методы, которые видны каждому классу в пакете, но не подклассам вне пакета.
Неважно, как сильно я об этом думаю, я все равно не вижу логики. Переключите модификаторы доступа и заставьте protected действовать так, как это работает в C++, и сохраните закрытый модификатор пакета таким, какой он есть, и это будет иметь смысл. Теперь нет.
В 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
}
В 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, хотя его очень трудно использовать его.
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