Существует несколько инструментов для изучения гольфа Perl. Один из них - perlsecret, который документирует «секретные операторы» и трюки, используемые многими игроками в Perl.
Для этого конкретного кода также важно понять, что такое -p
does. Он обертывает код в кучу другого кода, который затем можно использовать для игры в гольф.
Наконец, конечным инструментом для распаковки гольф-полей Perl является B::Deparse. Это переводит, как Perl понял код обратно в человеко читаемый Perl с отступом и тому подобное. Опция -p делает B :: Deparse добавлением скобок, даже если они не нужны, что может помочь прояснить приоритет. Параметр -d дает более точное представление объектов. Какие объекты? Обратите внимание.
$ perl -MO=Deparse,-p,-d
#!perl -lp
use bigint;$_=???<>+1:bnok{2*$_}$_
Use of ?PATTERN? without explicit operator is deprecated at - line 2.
BEGIN { $/ = "\n"; $\ = "\n"; }
use bigint;
LINE: while (defined(($_ = <ARGV>))) {
chomp($_);
BEGIN {
$^H{'bigint'} = '1';
$^H{'binary'} = 'CODE(0x7fc88ba3d580)';
$^H{'float'} = 'CODE(0x7fc88ba3d478)';
$^H{'integer'} = 'CODE(0x7fc88b298428)';
}
($_ = (?? ? (<ARGV> + bless({"sign" => "+","value" => [1]}, 'Math::BigInt')) : (bnok {
(bless({"sign" => "+","value" => [2]}, 'Math::BigInt') * $_)
} $_)));
}
continue {
(print($_) or die("-p destination: $!\n"));
}
- syntax OK
Некоторые из более эзотерических вещей это раскрывает ...
- ??? является оператором
?PATTERN?
и тройным оператором ?:
. В частности, ??
является условием тройной.
??
работает точно так же, как //
, но он будет соответствовать только один раз, пока не будет назначен reset
. Поскольку сброс никогда не вызывается в этой программе, он будет соответствовать только один раз для этой программы. //
будет соответствовать чему угодно.
use bigint
превращает все целые числа в объекты Math :: BigInt.
bnok
- метод биномиального коэффициента от Math::BigInt.
bnok
используется как косвенный вызов метода для целых чисел (которые действительно являются объектами Math :: BigInt). Косвенные вызовы методов имеют вид method $object @args
, поэтому bnok{2*$_}$_
- это фактически (2*$_)->bnok($_)
, который является central binomial coefficient.
Мясо программы может быть понято немного легче с некоторыми углублениями и вертикальными пробелами. Редактор с хорошим сочетанием парнов - это все, что вам нужно для их работы.
(
$_ =
(?? ? (<ARGV> + bless({"sign" => "+","value" => [1]}, 'Math::BigInt'))
: (bnok {(bless({"sign" => "+","value" => [2]}, 'Math::BigInt') * $_) } $_)
)
);
- Поскольку
??
будет соответствовать только один раз для всей программы, она используется, чтобы пропустить первую строку, которая является количество тестов.
- После первой строки
??
будет ложным, что вызовет расчет bnok
.
Есть одна деталь, которую я не разработал. Почему это <>+1
, а не <>
? Кажется, он подавляет пустую строку, но я не знаю почему.
Я значительно расширил свой ответ, чтобы выявить почти полное решение. – Schwern
Я полагаю, что +1 предназначен для обеспечения скалярного контекста. – tripleee