Warning: Wall of text approaching. It's a lot of small tricks I gathered over time.
Write your solutions as anonymous blocks
This was mentioned already but I'd like to reiterate it. In TIO, you can write my $f =
into the header, the block into the code proper, and start the footer with a ;
. This seems to be by far the shortest way to get the job done (since you don't need to care about reading any input, it's given to you in the arguments).
Another nice way is using the -n
or the -p
switch, but I didn't find a way to make it work in TIO.
Use the colon syntax for passing arguments
That is, instead of thing.method(foo,bar)
, you can do thing.method:foo,bar
and save 1 character. Unfortunately, you can't call another method on the result for obvious reasons, so it makes sense to use only for the last method in a block.
Use $_
as much as you can
Sometimes it's better to take a single list argument than several separate arguments because of this. When accessing $_
, you may call methods on it just by starting with a dot: e. g. .sort
is equal to $_.sort
.
However, bear in mind that each block gets its own $_
, so the parameters of the outer block won't propagate into the inner ones. If you need to access the parameters of the main function from an inner block, ...
Use the ^
variables if you can't use $_
Insert a ^
between the sigil and the variable name, like this: $^a
. These work only inside a block. The compiler first counts how many of these you have in the block, sorts them lexicographically, and then assigns the first argument to the first one, the second to the second one and so on. The ^
needs to be used only in the first occurrence of the variable. So {$^a - $^b}
takes 2 scalars and subtracts them. The only thing that matters is the alphabetical order, so {-$^b + $^a}
does the same thing.
If you ever feel like using the pointy block syntax (like ->$a,$b {$a.map:{$_+$b}}
), you're far better off writing bogus statement at the start of the block using the ^
for each argument you're not going to use in the main block (like {$^b;$^a.map:{$_+$b}}
) (Note that better way to golf this is {$^a.map(*+$^b)}
. I just wanted to show off the concept.)
Read through the operator docs carefully
The operators are very powerful and often they're the shortest way to get things done. Especially the meta-operators (operators that take operators as an argument) []
, [\]
, X
, <<
/>>
and Z
are worth of your attention. Don't forget that a meta-op can take another meta-op as an argument (like a XZ%%
I managed to use here). You can use >>
for a method call too, which can be a lot cheaper than a map (@list>>.method
instead of @list.map(*.method)
, but beware, they're not same!). And, finally, before you use a binary << >>
, bear in mind that Z
will often do the same thing in much fewer characters.
If you heap a lot of meta-ops onto each other, you can specify precedence using square brackets []
. That will save you when you pile up so many operators that it confuses the compiler. (That doesn't happen very often.)
Finally, if you need to coerce things to Bool, Int or Str, don't use the methods .Bool
, .Int
and .Str
, but rather the operators ?
, +
and ~
. Or even better, just put them into an arithmetic expression to force them into Int and so on. The shortest way to get the length of a list is +@list
. If you want to calculate 2 to the power of the length of a list, just say 2**@list
and it will do The Right Thing.
Use the free state variables $
, @
and %
In each block, every occurence of $
(or @
or %
) refers to a shiny new scalar (or array, or hash) state variable (a variable whose value persists across calls to the block). If you need a state variable that needs to be referenced only once in the source code, these three are your big friends. (Most often the $
.) For instance, in the Reverse Math Cycles challenge, it could be used to choose the operators cyclically from an array, which was indexed by $++%6
.
Use the sub forms of map
, grep
et al.
That means: do rather map {my block},list
than list.map({my block})
. Even if you manage to use list.map:{my block}
, these two approaches come out at the same number of bytes. And often, you would need to parenthesize the list when calling a method, but not when calling a sub. So the sub approach comes out always better or at least the same as the method one.
The only exception here is when the object which is to be map
ped, grep
ped and so on, is in $_
. Then .map:{}
obviously beats map {},$_
.
Use junctions (&
and |
) instead of &&
and ||
.
Obviously, they are 1 byte shorter. On the other hand, they must be collapsed by being forced into a boolean context. This can be always done with a ?
. Here you should be aware of a meta-op !
op
which forces bool context, uses op
and negates the result.
If you have a list and you want to turn it into a junction, don't use [&]
and [|]
. Instead use .any
and .all
. There is also .none
which cannot be so easily mimicked by the junction ops.
As a follow-up for this, you can also use Unicode exponents, even with multiple digits and/or a minus:
– Ramillies – 2017-08-31T14:16:31.303say (3² + 4², 2²⁰, 5⁻²)
==>(25 1048576 0.04)
. The complete list of Unicode you can abuse like this is here: https://docs.perl6.org/language/unicode_texas .