multi subs allow you to declare multiple overloaded versions of a function (subroutine, sub). Dispatch between sub bodies happens based on either the type(s) of arguments or based on a truth value of a "guard" - a boolean expression or boolean function placed after `where` in sub declaration head.
`%%` is a `modulo == 0` operator, which is surprisingly commonly needed.
`fizzbuzz(Int $ where * %% 15)` can also be written `fizzbuzz(Int $x where $x %% 15)` - the difference is that you don't have to name the argument just for the check. When `fizzbuzz` is called, all known definitions' guards are checked to see which will be entered.
The `*` in `* %% 15` is "whatever star", you can think of it as a short syntax for creating lambdas. There are multiple ways of constructing anonymous functions and blocks, you can get the same effect with `{ $_ %% 15 }`, `-> $a { $a %% 15 }`.
`»` is a "hyper operator"; the next method-call will be performed on all elements of a collection on the left. Groovy uses `*.` for this I think. You could use a `.map` method instead, `(1..100).map(&fizzbuzz)` or `.map({ .&fizzbuzz })` (`{ .meth }` is equivalent to `-> $x { $x.meth }`)
`.&` is a "call as method" operator: `fizzbuzz` is a function, so you can't call `1.fizzbuzz`, however, you can call `1.&fizzbuzz`.
Also, in the first solution, `(3 & 5)` is a Junction. This is an important concept that introduces a degree of nondeterminism to the language - well worth reading about! :)