Попередження : наближається стіна тексту. Це дуже багато маленьких хитрощів, які я зібрав з часом.
Пишіть свої рішення як анонімні блоки
Про це вже згадувалося, але я хотів би ще раз зазначити це. У 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
і це зробить правильну річ.
Використовуйте вільні змінні стану $
, @
і%
У кожному блоці кожне виникнення $
(або @
або %
) посилається на нову блискучу скалярну (або масив, або хеш) змінну стану (змінна, значення якої зберігається у викликах до блоку). Якщо вам потрібна змінна стан, на яку потрібно посилатися лише один раз у вихідному коді, ці троє - ваші великі друзі. (Найчастіше $
.) Наприклад, у виклику Reverse Math Cycles це може бути використано для вибору операторів циклічно з масиву, який індексувався$++%6
.
Використовуйте підформи map
,grep
і ін.
Це означає: робити, а map {my block},list
не робити list.map({my block})
. Навіть якщо вам вдасться використовуватиlist.map:{my block}
, ці два підходи виходять при однаковій кількості байтів. І часто вам потрібно скористатись дужкою списку під час виклику методу, але не під час виклику суб. Таким чином, підхід завжди виходить кращим або, принаймні, таким же, як і метод.
Єдиним винятком тут є те, коли знаходиться об'єкт, який має бути map
пед, grep
пед тощо $_
. Тоді .map:{}
явно б’є map {},$_
.
Використовуйте переходи ( &
і|
) замість &&
і ||
.
Очевидно, вони на 1 байт коротші. З іншого боку, вони повинні бути згорнуті, будучи примушеними до булевого контексту. Це завжди можна зробити за допомогою a ?
. Тут ви повинні знати про мета-оп!
op
яка змушує розкривати контекст, використовувати op
і заперечувати результат.
Якщо у вас є список і ви хочете перетворити його на перехід, не використовуйте [&]
і [|]
. Замість використання .any
і .all
. Існує також те, .none
що не може так легко імітуватися перемикачем.
say (3² + 4², 2²⁰, 5⁻²)
==>(25 1048576 0.04)
. Повний список Unicode, який ви можете зловживати таким чином, тут: docs.perl6.org/language/unicode_texas .