Raku Programming/Blocks and Closures

About Blocks
When we talked about subroutines we saw that a subroutine declaration consisted of three parts: The subroutine name, the subroutine parameter list, and the code block of subroutine internals. Blocks are very fundamental in Raku, and we're now going to use them to do all sorts of cool things.

We've seen a few blocks used in various constructs already:

All these blocks serve the purpose of grouping lines of code together for a particular purpose. In an  block, the statements inside the block are all executed when the   condition is true. The entire block is not executed if the condition is false. In a loop, all the statements in the loop block are executed together in repetition.

Scope
In addition to keeping like code together, blocks also introduce the notion of scope. variables defined inside a block are not visible outside it. Scope ensures that variables are only used when they are needed, and they are not being modified when they are not supposed to be. Blocks don't need to be associated with any particular construct, like an  or a. Blocks can exist all by themselves:

The example shows the idea of scope very nicely: The variable  inside the block is not the same as the variable   outside the block. Even though they have the same name, they have a different scope. Here's a slightly different example:

The variable  is visible from the point where it was defined and inside all scopes inside the scope where it was defined too. however is only visible inside the block it was defined in, and the block inside that. is only visible in the innermost block.

Scope Variables
Scopes can be specified exactly in cases where there is ambiguity. We can use keywords like  to specify a variable from the scope directly above the current scope:

Subroutines have access to the scope from which they are called using the  scope, assuming that the variable in the outer scope was declared as  :

Coderefs
Blocks can be stored in a single scalar variable as a coderef. Once stored in a coderef variable, the block can be executed like a regular subroutine reference:

Closures
We see in the example above that a block can be stored in a variable. This action creates a closure. A closure is a stored block of code that saves its current state and current scope, which can be accessed later. Let's see a closure in action:

The closure saves a reference to the  variable when the closure is created. Even if that variable is not in scope anymore when the code block is executed.

When we change $x later on, the closure will see the changed value, so if you want to create multiple closures with different enclosed variables, you have to create a new variable each time:

Pointy Blocks
We can use the  keyword to create a subroutine or a subroutine reference. This isn't the only syntax to do this, and in fact is a little bit more verbose then it needs to be for the common case of an unnamed ("anonymous") subroutine or subroutine reference. For these, we can use a construct called a pointy block. Pointy blocks, which are called lambda blocks in other languages, are very useful. They can create a code reference like an anonymous subroutine, and they can also create blocks of code with parameters. A pointy block is a lot like an unnamed subroutine. More generally, it's like a block with parameters. We've seen pointy blocks briefly when we talked about loops. We used pointy blocks in association with a looping construct to give names to the loop variable instead of relying on the default variable. This is why we used pointy blocks in these situations: They enable us to specify variable names to use as parameters to an arbitrary block of code.

We'll show a few examples:

Placeholder Arguments
In a block, if we don't want to go through the hassle of writing out an argument list, we can use placeholder arguments. Placeholders use the special  twigil. Passed values are assigned to placeholder variables in alphabetical order: