Какие общие советы у вас есть для игры в гольф в Perl 6? Я ищу идеи, которые могут быть применены к задачам по коду для гольфа в целом, которые, по крайней мере, несколько специфичны для Perl 6 (например, «удалить комментарии» - это не ответ). Пожалуйста, оставьте один совет за ответ.
Обратите внимание, что Perl 6 не является Perl 5, поэтому этот вопрос не является дубликатом. Большинство советов по игре в Perl 5 просто не относятся к Perl 6.
say (3² + 4², 2²⁰, 5⁻²)
==>(25 1048576 0.04)
. Полный список Unicode, который вы можете использовать следующим образом: docs.perl6.org/language/unicode_texas .Изучите функции для чтения ввода. В Perl 6 есть много интересных функций, которые могут легко читать входные данные из ARGV или STDIN (если ничего не было указано в ARGV), которые могут сократить ваш код при правильном использовании. Если вы вызываете их как методы файлового дескриптора, вы можете заставить их работать с определенным файловым дескриптором (полезно, например, если вы читаете из
STDIN
, но вы должны читать аргументы в ARGV).get
Эта функция получает одну строку и автоматически ее обрабатывает, поэтому вам не нужно это делать. Это полезно, если вам нужно прочитать только одну строку.
lines
Эта функция получает все строки из файла или STDIN. Это ленивый список, поэтому, если вы используете его
for
, он будет читать только то, что вам нужно. Например.slurp
Это прочитает весь файл или STDIN и вернет результат в виде одной строки.
источник
say "<$_>" for lines
работает сейчасПредупреждение : приближается стена текста. Со временем я собрал много маленьких хитростей.
Напишите ваши решения как анонимные блоки
Это уже упоминалось, но я хотел бы повторить это. В 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
что не может быть так легко подражать соединительным операциям.источник
&&
и||
все еще полезно для короткого замыкания?Уменьшите пространство, используемое для переменных
В этом есть несколько частей.
Удалить пробелы
Переменные, объявленные с использованием,
my
обычно могут быть объявлены без пробела междуmy
и именем переменной.my @a
эквивалентноmy@a
.Используйте переменные без сигилов
Вы можете объявить переменные, используя обратную косую черту, чтобы удалить сигил перед именем переменной, например:
(к сожалению, вы не можете удалить пробел :()
Это полезно, так как позже вы можете ссылаться на них как на простое имя переменной.
В основном это экономит байты, если вы используете переменную более одного раза в другом месте вашего кода. Недостатком является то, что переменная должна быть инициализирована.
Используйте
$!
и$/
Эти предварительно объявленные переменные обычно используются соответственно для исключений и регулярных выражений, но их не нужно определять с помощью
my
.Особенно полезно использовать
$/
в качестве массива и использовать ярлыки с$
последующим номером для доступа к этому элементу$/
массива;источник
использование
...
вместоfirst
Как правило, если вы хотите найти первое число, соответствующее некоторому условию
&f
, вы можете представить его следующим образом:Однако вместо этого вы можете использовать
...
оператор:Если вы должны начать с
0
, вы можете иметь-1
потом вместо+
.Если вы хотите индекс первого элемента в списке,
@a
который имеет условие&f
, обычно вы делаете:Вместо:
(или наоборот, если вы хотите, чтобы 0 было проиндексировано). Таким же образом вы можете получить все элементы до первого, который проходит условие.
Недостатком этого является то, что список должен пройти условие в какой-то момент, в противном случае
...
оператор попытается экстраполировать конец списка и, скорее всего, выдаст ошибку. Вы также не можете использовать любой код в левой части, так как он будет интерпретирован как часть последовательности.источник