Из эмпирического тестирования кажется, что 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:
var x = 1;
function weird(){
return x;
var x = 2;
}
weird () возвращает undefined ... x «принято», хотя присвоение никогда не происходило.
Точно так же, но не так неожиданно
function weird2(){
var x;
return x();
function x(){ return 2 };
}
возвращает 2.
Ruby
Time.parse
часто делает вид, что парсинг не завершился неудачей, возвращая вместо этого now
require 'time'
Time.parse '2000-01-01 12:00:00'
# -> 2000-01-01 12:00:00 +0100
Time.parse '2000-99-01 00:00:00'
# -> ArgumentError: argument out of range ...
Time.parse 'now'
# -> 2010-08-13 21:26:13 +0200
Time.parse 'yesterday'
# -> 2010-08-13 21:26:18 +0200
Time.parse 'billion years ago'
# -> 2010-08-13 21:26:37 +0200
На Java,
int x = 010;
Это присваивает x значение 8.
Любое целое число, которому в Java предшествует ноль, считается восьмеричным.
Однажды я написал язык программирования, в котором был оператор "strfry":
"hello world"?
# => "wdo rlholle"
Полезный, да?
.В MAXScript все операторы обрабатываются одинаково. Итак, a = b + c
устанавливает a
равным b
, затем вычисляет сумму a+c
, и отбрасывает результат.
В C:
warning C4013: 'myfunc' undefined; assuming extern returning int
почему-то я помню, что не видел предупреждений (их слишком много в каком-то старом коде?) и загадывался, почему преобразование из int приводит к ошибке компилятора, где используется невозвратная функция.
Компилятор предполагая, что подобные вещи были совершенно неожиданны.
. Это отсутствие особенности, которая является странной: На питоне отсутствует утверждение switch
(хотя обходные пути существуют).
Еще один Си-изм.
int i= 0;
while( i != 12 ) {
/* Some comment
i += 1;
/* Another comment */
}
Почему он не работает? Линт скажет тебе. Однако компилятор Си, как правило, проходит через это блаженство. Как и я.
Это был настоящий момент WTF, когда я понял, что не так.
В Форте есть несколько странных вещей о его структурах управления. Во-первых, поскольку это язык обратной польской нотации, условие предшествует IF
, так как в:
x 0 = IF
Теперь, чтобы закрыть условный блок, используется ключевое слово THEN
:
x 0 = IF ." Equals zero!" THEN
Теперь начинается реальный WTF. Что делает IF
, так это компилирует условный форвардный скачок и помещает на стек адрес смещения скачка. Когда THEN
найден, он вытаскивает этот адрес из стека, вычисляет фактическое смещение, а затем компилирует его. С другой стороны, ELSE
, компилируя смещение в прямом направлении, выталкивает адрес из стека, выталкивает новый адрес из стека, вычисляет смещение для выпавшего адреса, а затем компилирует это смещение. Синтаксис имеет следующий смысл:
x 0 = IF ." Equals zero!" ELSE ." Not equal to zero!" THEN
Первое и второе утверждения компилируются следующим образом:
x LITERAL 0 = (0BRANCH) LITERAL offset SLITERAL" Equals zero!" (DOTQ)
x LITERAL 0 = (0BRANCH) LITERAL offset SLITERAL" Equals zero!" (DOTQ) BRANCH LITERAL offset SLITERAL" Not equal to zero!" (DOTQ)
Для усложнения странности это поведение не является скрытым. Оно является частью ANSI спецификации языка и может быть свободно использовано, как путем построения пользовательских структур управления потоком, так и путем их интересного комбинирования. Например, возьмем цикл Форта WHILE
:
BEGIN x 10 < WHILE x 1+ to x REPEAT
Часть между BEGIN
и WHILE
является произвольным кодом, так что на самом деле можно получить код, выполняемый до и после условного теста в одной структуре управления. Это по замыслу, но следующее, хотя и разрешено, не является:
BEGIN DUP 2 > WHILE DUP 5 < WHILE DUP 1+ REPEAT 123 ELSE 345 THEN
Который использует то, как каждое управляющее слово потока работает, чтобы объединить два WHILE
оператора и, для загрузки, добавить различный пост-петлевой код для каждого выхода. И чтобы показать, что я не шучу, я просто скопировал этот маленький фрагмент из кода в интернете, с небольшими изменениями для его упрощения.
Чтение строки из текстового файла на Java.
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader("filename"));
String str;
str = in.readLine();
if (str != null) {
...
}
} catch (IOException e) {
...
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {}
}
Фу. Хотя я признаю, что это не странно... просто зло. :-)
Более короткая, более идиоматическая версия:
try {
BufferedReader in = new BufferedReader(new FileReader("filename"));
try {
String str = in.readLine();
while (str != null) {
str = in.readLine();
}
} finally {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
Java Generics это ВТФ:
List<String> ls = new ArrayList<String>(); //1
List<Object> lo = ls; //2
2: Это противозаконно (???), это загадка, но вы должны подумать, что может случиться дальше:
lo.add(new Object());
String s = ls.get(0);
Мы бы присвоили Объекту ссылку на Строку, о нет! И вот так, вокруг них куча всего этого.
Самая странная особенность, о которой я знаю, взята из мира C ++: SFINAE .
Хуже всего то, что он оказался очень полезным, широкое использование SFINAE в BOOST для меня является достаточным доказательством.
Для меня это определенно модификатор PLEASE
в INTERCAL.
Если PLEASE
появляется недостаточно часто, то программа считается недостаточно вежливой, и сообщение об ошибке говорит об этом; если слишком часто, то программа может быть отклонена как чрезмерно вежливая.
C ++:
void f(int bitand i){ //WTF
i++;
}
int main(){
int i = 0;
f(i);
cout << i << endl; //1
return 0;
}
Около 20 лет назад я работал с компилятором для языка под названием Coral, который позволил мне объявить Vightonly
Переменные!
Это имело смысл, хотя, поскольку они были глобальными и использованы в качестве механизма сигнализации. Один процесс написал бы значение, а другой прочитал его.
PHP как весь язык - это в основном WTF.
Определение языка определяется (см. Www.php.org) не грамматикой или стандартом, а набором разделов «вы можете написать этот пример » (можете ли вы написать что-нибудь иначе, конечно, просто угадайте обобщение), с откровенными комментариями пользователей, говорящими «но он делает эту дурацкую штуку ...».
Я периодически сталкиваюсь с сбоями в работе созданного нами синтаксического анализатора PHP. Вот последнее:
"abc$A[define]def"
Теперь PHP является (действительно плохой) копией PERL, и поэтому он позволяет создавать строки с неявной подстановкой переменных. $ X в строке говорит «вставить значение $ X в строку», что эквивалентно «abc». $ X. "def" где "." - это оператор конкатенации строк в PHP.
$ A [7] в строке говорит: «вставить значение седьмого слота массива $ A в строку», что эквивалентно «abc». $ A [7]. "def".
Теперь на языке (веб-сайте) ясно сказано, что «определить» - это ключевое слово, и вы не можете использовать его везде, где найдете выражение. Итак, что делает вышеприведенный драгоценный камень, содержащий слово «определить»? Выкинуть синтаксическую ошибку? Нет, это имело бы смысл.
Нет, на самом деле это означает:
"abc" . $A["define"] . "def"
Он делает это ТОЛЬКО, если вы пишете вещь, которая выглядит как идентификатор (ключевое слово или нет!) В простом доступе к массиву в строке. Больше нигде в языке такое поведение не встречается. Что, писать "abc $ A [" define "] def" было неразумно, поэтому изобретателям PHP пришлось это добавить? Дай мне перерыв. (Чтобы усугубить уголовное преступление, существует «доступ к сложному массиву в строке», и, конечно, он работает по-другому. Обратите внимание на «abc {$ A [define]} def»; это незаконно согласно веб-сайту PHP.
(Turnns out массивы PHP являются ассоциированными хэшами, поэтому поиск члена массива (ну, хеш-таблицы) по имени не является ужасной идеей).
Язык полон подобных подводных камней. вещь, которую я нашел сегодня в подпрограмме ", вам следует переключиться на PHP.
Лямбда-выражения C ++ 1x:
[] (int x) { std::cout << x << std::endl; } ();
Этим можно злоупотреблять из-за нечетного синтаксиса:
[](){}();[]{[]{}();}();
Это полностью допустимый C ++ 1x.
Найдено при изучении PowerShell:
Попробуйте угадать, как выглядит полученный массив:
$a = 1, 2
$b = 1, 2+3
$c = 1, 2*3
Ответы:
1, 2
1, 2, 3
1, 2, 1, 2, 1, 2
Ай! Это пошатнуло мою веру в PowerShell и людей, стоящих за ним.
PHP
Из онлайн-документации:
string implode ( string $glue , array $pieces )
- объединить элементы массива строкой
Примечание: implode() может, по историческим причинам, принимать свои параметры в любом порядке.
Так что это работает: implode($someArray, $glue)
Надеюсь, в PHP 6 эти исторические причуды будут устранены.
В PHP:
for ($s="a";$s<="z";$s++) echo $s.' ';
Это будет писать:
a b c d e .. .w x y z aa ab ac ad .. ay az ba bb bc ... by bz ca cb ... yz za zb ... zx zy zz
В JavaScript это:
var something = 12;
function nicelyCraftedFunction()
{
something = 13;
// ... some other code
// ... and in Galaxy far, far away this:
if( false ) // so the block never executes:
{
var something;
}
}
nicelyCraftedFunction(); // call of the function
Обычно вы ожидаете, что переменная something
получит значение 13.
Но не в JavaScript - переменные там имеют область действия, поэтому более позднее объявление влияет на все восходящее.
В языках, использующих нотацию C / C ++ / Java (например, JS), можно ожидать, что переменные имеют область видимости блока, а не так ...
Таким образом, мертвый блок кода, который компилятор может даже удалить из окончательно сгенерированного байт-кода, все еще имеет побочные эффекты в остальной части кода, который выполняется нормально.
Следовательно что-то
будет по-прежнему 12
- не измениться после вызова функции.
Самой странной функцией, с которой я когда-либо сталкивался, был оператор "RETURN n" в диалекте BASIC (не помню, в каком именно, это было около 28 лет назад). "n" было необязательным и по умолчанию равнялось 1. Это могло быть положительное или отрицательное число, которое указывало, какая строка относительно вызывающего GOSUB будет выполняться следующей.
Например, следующее выводило "30":
10 GOSUB 200
20 PRINT "20"
30 PRINT "30"
100 END
200 RETURN +2
Я столкнулся с этим, когда мне нужно было перевести программу, написанную на этом странном BASIC, на FORTRAN. Программа на BASIC довольно часто использовала эту функцию для возврата к различным утверждениям, основанным на различных условиях, и мне потребовалось некоторое время, чтобы понять логический поток. Когда я понял ее, я смог написать гораздо более простую версию программы. Излишне говорить, что в более простой версии на FORTRAN было меньше ошибок, чем в оригинальной программе на BASIC.
В Perl объекты - это просто благословение
ed ссылки, поэтому изменение класса объекта во время выполнения - это кусок пирога:
package Foo;
sub new { bless {}, $_[0] }
package Bar;
package main;
my $foo = Foo->new;
ref($foo); # => "Foo"
bless $foo, 'Bar';
ref($foo); # => "Bar"
Я удивился, что другие языки не могут этого сделать. Какая полезная функция!
MySQL enums, а именно их способность спутать живой ад с неподготовленными коллегами.
CREATE TABLE foo (
....
dispatched ENUM('0','1') NOT NULL DEFAULT '0',
)
Затем:
UPDATE TABLE foo SET ..., dispatched = 1;
Упс, отправленный
был установлен на НУЛЬШЕ, потому что 1 не был процитирован. Это действительно раздражало того, кто работал над моим кодом; теперь я использую обычные старые INTs.
На одной из связанных записей, даже если вы добавите опцию пустой строки в ваше перечисление, например
blah ENUM('','A','B') NOT NULL,
Если вы присвоите недопустимое значение blah
, MySQL будет использовать секретное скрытое пустое строковое значение для представления недопустимого значения, которое будет трудно отличить от того, которое вы добавили сами. Ура!
в X++ (Microsoft Dynamics AX):
1) необходимость полустолбца (;) в отдельной строке для отделения объявления переменных от высказываний (по крайней мере до версии 4.0)
int i;
int myArray[5];
;
i = 1;
2) индексы массивов основаны на 1, поэтому нельзя читать из массива с использованием индекса 0 (нуля), как в
int myArray[5];
;
print myArray[0]; // runtime error
, это не странно, но можно использовать нулевой индекс с левой стороны ассиметра, как в
int myArray[5];
;
myArray[2] = 102;
myArray[0] = 100; // this is strange
print myArray[2]; // expcting 102?
что происходит? Массив инициализируется на значение по умолчанию , независимо от того, какое значение было использовано в присваивании. Вышеуказанный код выводит 0 (ноль)!
Десятки вещей в Javascript могут заставить глаза слезть.
Обзор локальных переменных, как один простой пример:
function foo(obj)
{
for (var n = 0; n < 10; n++)
{
var t; // Here is a 't'
...
}
t = "okay"; // And here's the same 't'
}
VBScript's With blocks:
With xml.appendChild(xml.createElement("category"))
.setAttribute("id",id)
.setAttribute("keywords",keywords)
With .appendChild(xml.createElement("item"))
.setAttribute("count",count)
.setAttribute("tip",tip)
.appendChild(xml.createTextNode(text))
End With
End With