Предупреждение : приближается стена текста. Со временем я собрал много маленьких хитростей.
Напишите ваши решения как анонимные блоки
Это уже упоминалось, но я хотел бы повторить это. В TIO вы можете написать my $f =
в заголовок, блок в собственно код, и запустить нижний колонтитул с;
. Похоже, что это самый короткий способ выполнить работу (поскольку вам не нужно заботиться о том, чтобы прочитать какие-либо входные данные, они даются вам в аргументах).
Еще один хороший способ использования -n
или-p
переключателя , но я не нашел способа заставить его работать в TIO.
Используйте синтаксис двоеточия для передачи аргументов
То есть вместо thing.method(foo,bar)
, что вы можете сделатьthing.method:foo,bar
и сохранить 1 символ. К сожалению, вы не можете вызвать другой метод для результата по очевидным причинам, поэтому имеет смысл использовать его только для последнего метода в блоке.
использование $_
как можно больше
Иногда из-за этого лучше взять один аргумент списка, чем несколько отдельных аргументов. При обращении к нему $_
вы можете вызывать методы, просто начав с точки: например,.sort
, равно$_.sort
.
Однако имейте в виду, что каждый блок получает свой $_
, поэтому параметры внешнего блока не будут распространяться на внутренние. Если вам нужно получить доступ к параметрам основной функции из внутреннего блока, ...
Использовать ^
переменные, если вы не можете использовать$_
Вставьте ^
между сигилами и именем переменным, как это: $^a
. Они работают только внутри блока. Компилятор сначала подсчитывает, сколько из них есть в блоке, сортирует их лексикографически, а затем назначает первый аргумент первому, второй - второму и так далее. Эти ^
потребности , которые будут использоваться только в первом упоминании переменной. Так что {$^a - $^b}
берет 2 скаляра и вычитает их. Единственное, что имеет значение, это алфавитный порядок, так {-$^b + $^a}
же, как и то же самое.
Если вам когда-нибудь захочется использовать синтаксис заостренного блока (например ->$a,$b {$a.map:{$_+$b}}
), вам гораздо лучше писать фиктивную инструкцию в начале блока, используя ^
для каждого аргумента, который вы не собираетесь использовать в основном блоке (например {$^b;$^a.map:{$_+$b}}
) (Примечание это лучший способ игры в гольф {$^a.map(*+$^b)}
. Я просто хотел показать концепцию.)
Операторы очень мощные и часто они являются самым коротким способом добиться цели. Особенно мета-операторы (операторы, принимающие операторы в качестве аргумента) []
, [\]
, X
, <<
/ >>
и Z
стоит вашего внимания. Не забывайте , что мета-оп может занять другой мета-цит в качестве аргумента (например, XZ%%
мне удалось использовать здесь ). Вы также можете использовать >>
для вызова метода, который может быть намного дешевле, чем карта ( @list>>.method
вместо @list.map(*.method)
, но будьте осторожны, они не то же самое! ). И, наконец, прежде чем использовать двоичный файл << >>
, имейте в виду, чтоZ
он часто делает то же самое с гораздо меньшим количеством символов.
Если вы наложили много мета-операций друг на друга, вы можете указать приоритет, используя квадратные скобки []
. Это спасет вас, когда вы соберете столько операторов, что это смущает компилятор. (Это случается не очень часто.)
Наконец, если вам нужно , чтобы заставить вещи в Bool, Int или Str, не используйте методы .Bool
, .Int
и .Str
, а операторы ?
, +
и ~
. Или, что еще лучше, просто поместите их в арифметическое выражение, чтобы ввести их в Int и так далее. Самый короткий способ получить длину списка - +@list
. Если вы хотите вычислить 2 в степени длины списка, просто скажите2**@list
и это будет правильно.
Используйте свободные переменные состояния $
, @
и%
В каждом блоке каждое вхождение $
(или @
или %
) ссылается на новую блестящую скалярную (или массив, или хэш) переменную состояния (переменная, значение которой сохраняется при обращении к блоку). Если вам нужна переменная состояния, на которую нужно ссылаться только один раз в исходном коде, эти три - ваши большие друзья. (Чаще всего $
.) Например, в задаче « Обратные математические циклы» его можно использовать для циклического выбора операторов из массива, который был проиндексирован $++%6
.
Используйте подформы map
, grep
и соавт.
Это означает: делать, а map {my block},list
не list.map({my block})
. Даже если вам удастся использовать list.map:{my block}
, эти два подхода выходят с одинаковым количеством байтов. И часто вам нужно заключать в скобки список при вызове метода, но не при вызове подпрограммы. Таким образом, дополнительный подход всегда лучше или, по крайней мере, такой же, как метод.
Единственное исключение здесь, когда объект, который должен быть map
ped, grep
ped и так далее, находится в $_
. Тогда .map:{}
явно бьет map {},$_
.
Используйте соединения ( &
и |
) вместо &&
и ||
.
Очевидно, они на 1 байт короче. С другой стороны, они должны быть свернуты, будучи вынужденными в логический контекст. Это всегда можно сделать с помощью ?
. Здесь вы должны знать о мета-операции, !
op
которая вызывает контекст bool, используетop
и отменяет результат.
Если у вас есть список, и вы хотите превратить его в соединение, не используйте [&]
и [|]
. Вместо этого используйте .any
и .all
. Существует также то, .none
что не может быть так легко подражать соединительным операциям.
say (3² + 4², 2²⁰, 5⁻²)
==>(25 1048576 0.04)
. Полный список Unicode, который вы можете использовать следующим образом: docs.perl6.org/language/unicode_texas .