Советы по игре в гольф в Перл 6


16

Какие общие советы у вас есть для игры в гольф в Perl 6? Я ищу идеи, которые могут быть применены к задачам по коду для гольфа в целом, которые, по крайней мере, несколько специфичны для Perl 6 (например, «удалить комментарии» - это не ответ). Пожалуйста, оставьте один совет за ответ.

Обратите внимание, что Perl 6 не является Perl 5, поэтому этот вопрос не является дубликатом. Большинство советов по игре в Perl 5 просто не относятся к Perl 6.

Ответы:


9

Избегайте subлитералов. Во многих случаях вы можете просто использовать {}для блоков кода. Например, не пишите следующий код.

sub ($a){$a*2}

Вместо этого используйте синтаксис блоков. Это также позволяет использовать $_, @_и %_шаблонные переменные, если вам нужно только одну переменную. Если вам нужно больше, вы можете использовать $^a, $^bпеременные, и так далее.

{$_*2}

Кроме того, в некоторых редких случаях можно использовать любой код (особенно когда у вас есть простые выражения). *Заменяет заполнитель аргумент.

* *2

8

В Perl 6 есть очень странная функция, позволяющая использовать все символы Юникода в категориях Nd , Nl и  No в качестве литералов рациональных чисел. Некоторые из них короче, чем запись их числовых значений в ASCII:

  • ¼(2 байта) короче .25или1/4 (3 байта).
  • ¾(2 байта) короче .75или3/4 (3 байта).
  • (3 байта) короче 1/16 (4 байта).
  • 𐦼 (4 байта) короче 11/12(5 байтов).
  • 𒐲 (4 байта) короче 216e3(5 байтов).
  • 𒐳(4 байта) короче 432e3(5 байтов).

В качестве продолжения этого вы также можете использовать показатели Unicode, даже с несколькими цифрами и / или минусом: say (3² + 4², 2²⁰, 5⁻²)==> (25 1048576 0.04). Полный список Unicode, который вы можете использовать следующим образом: docs.perl6.org/language/unicode_texas .
Ramillies

8

Изучите функции для чтения ввода. В Perl 6 есть много интересных функций, которые могут легко читать входные данные из ARGV или STDIN (если ничего не было указано в ARGV), которые могут сократить ваш код при правильном использовании. Если вы вызываете их как методы файлового дескриптора, вы можете заставить их работать с определенным файловым дескриптором (полезно, например, если вы читаете из STDIN, но вы должны читать аргументы в ARGV).

get

Эта функция получает одну строку и автоматически ее обрабатывает, поэтому вам не нужно это делать. Это полезно, если вам нужно прочитать только одну строку.

lines

Эта функция получает все строки из файла или STDIN. Это ленивый список, поэтому, если вы используете его for, он будет читать только то, что вам нужно. Например.

say "<$_>"for lines

slurp

Это прочитает весь файл или STDIN и вернет результат в виде одной строки.


Эта ошибка была исправлена ​​- не знаю, когда, но say "<$_>" for linesработает сейчас
кошка

5

Предупреждение : приближается стена текста. Со временем я собрал много маленьких хитростей.

Напишите ваши решения как анонимные блоки

Это уже упоминалось, но я хотел бы повторить это. В 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}, эти два подхода выходят с одинаковым количеством байтов. И часто вам нужно заключать в скобки список при вызове метода, но не при вызове подпрограммы. Таким образом, дополнительный подход всегда лучше или, по крайней мере, такой же, как метод.

Единственное исключение здесь, когда объект, который должен быть mapped, grepped и так далее, находится в $_. Тогда .map:{}явно бьет map {},$_.

Используйте соединения ( &и |) вместо &&и ||.

Очевидно, они на 1 байт короче. С другой стороны, они должны быть свернуты, будучи вынужденными в логический контекст. Это всегда можно сделать с помощью ?. Здесь вы должны знать о мета-операции, !opкоторая вызывает контекст bool, используетop и отменяет результат.

Если у вас есть список, и вы хотите превратить его в соединение, не используйте [&]и [|]. Вместо этого используйте .anyи .all. Существует также то, .noneчто не может быть так легко подражать соединительным операциям.


1
Я думаю, &&и ||все еще полезно для короткого замыкания?
Только для ASCII

@ Только для ASCII: Да, конечно.
Рамилли

4

Уменьшите пространство, используемое для переменных

В этом есть несколько частей.

Удалить пробелы

Переменные, объявленные с использованием, myобычно могут быть объявлены без пробела между myи именем переменной. my @aэквивалентноmy@a .

Используйте переменные без сигилов

Вы можете объявить переменные, используя обратную косую черту, чтобы удалить сигил перед именем переменной, например:

my \a=1;

(к сожалению, вы не можете удалить пробел :()

Это полезно, так как позже вы можете ссылаться на них как на простое имя переменной.

 a=5;
 a.say

В основном это экономит байты, если вы используете переменную более одного раза в другом месте вашего кода. Недостатком является то, что переменная должна быть инициализирована.

Используйте $!и$/

Эти предварительно объявленные переменные обычно используются соответственно для исключений и регулярных выражений, но их не нужно определять с помощью my.

$!=1;
$/=5;

Особенно полезно использовать $/в качестве массива и использовать ярлыки с $последующим номером для доступа к этому элементу $/массива;

$/=100..200;
say $5;  #105
say $99; #199

2

использование ... вместоfirst

Как правило, если вы хотите найти первое число, соответствующее некоторому условию &f, вы можете представить его следующим образом:

first &f,1..*

Однако вместо этого вы можете использовать ...оператор:

+(1...&f)

Если вы должны начать с 0, вы можете иметь -1потом вместо +.

Если вы хотите индекс первого элемента в списке, @aкоторый имеет условие &f, обычно вы делаете:

first &f,@a,:k

Вместо:

(@a...&f)-1

(или наоборот, если вы хотите, чтобы 0 было проиндексировано). Таким же образом вы можете получить все элементы до первого, который проходит условие.

Недостатком этого является то, что список должен пройти условие в какой-то момент, в противном случае ...оператор попытается экстраполировать конец списка и, скорее всего, выдаст ошибку. Вы также не можете использовать любой код в левой части, так как он будет интерпретирован как часть последовательности.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.