While you may want to go directly to the src/core/Hash.pm6 file to see the definitions of the methods, you will not find them there. The Hash class is a child of Map, and all these methods are defined in src/core/Map.pm6. Getting keys and values is simple:

As you see, the method returns a sequence that is built using an anonymous class implementing the Rakudo::Iterator::Mappy role. We already saw how this approach is used in combination with defining pull-one and push-all methods.

Let us look at another set of methods, pairs and antipairs. One of them is simple and straightforward:

In this case, you’ll see the following output for the test examples above:

> 2⁵
# a = 2
# b = 5
> 10¹²
# a = 10
# b = 12

Now, it is time to understand how the postfix that extracts superscripts works. Its name, ⁿ, written in superscript, should not mislead you. This is not a magic trick of the parser, this is just a name of the symbol, and it can be found in the Grammar:

Hello! Yesterday, I was giving my Perl 6 Intro course at the German Perl Workshop in Gummersbash. It was a great pleasure to prepare and run this one-day course, and, while it was difficult to cover everything, we touched all main aspects of the Perl 6 language: from variables to regexes and parallel computing. Of course, it was only a top-level overview, and there was not enough time to make all the exercises. You can do them at home, here’s the Perl 6 Intro – Exercises PDF file.

Among the rest, we tried to implement the sleep method for integers. The rationale behind that is that it is possible to say:

> 10.rand
9.9456903794802

But not:

> 10.sleep
No such method 'sleep' for invocant of type 'Int'
in block <unit> at <unknown file> line 1

OK, so let’s first implement the simplest form of sleep for Ints only. Go to src/core/Int.pm6 and add the following:

What can be changed here? The first idea is to allow non-integer numbers as the delay duration. As Int does the Real role, just move the method to src/core/Real.pm and get the value using the Num method instead of reading $!value directly (there is no such attribute in the Real role):

my role Real does Numeric {
method sleep() { nqp::sleep(self.Num); }

Now it also works with rationals and floating-point numbers:

> 2.sleep
2
> 3.14.sleep
3.14
> pi.sleep
3.14159265358979

Before wrapping it up, let us take a look at the body of the sleepsubroutine. It is defined in src/core/Date.pm6:

And maybe just to see why our modified Rakudo printed the time after sleep in the tests above, let’s refer to the documentation of NQP to see that its sleep function’s return value is the number of seconds:

## sleep
* `sleep(num $seconds --> num)`
Sleep for the given number of seconds (no guarantee is made
how exact the time sleeping is spent.)
Returns the passed in number.

Having this said, you can use the new name as a type name and create variables of that type:

my colour $c;
$c = green;
say $c; # green
say $c.Int; # 3

As you would rightly expect, the type of the variable is very predictable:

say $c.^name; # colour

Now, try to find the class implementation in Rakudo sources. Surprisingly, there is no file src/core/Enum.pm, but instead, there is src/core/Enumeration.pm. Looking at that file, you cannot say how our program works. Let us dig a bit.

In Perl 6, you can ask the sequence operator to build a desired sequence for you. It can be arithmetic or geometric progression. All you need is to show the beginning of the sequence to Perl, for example:

.say for 3, 5 ... 11;

This prints numbers 3, 5, 7, 9, and 11. Or:

.say for 2, 4, 8 ... 64;

This code prints powers of 2 from 2 to 64: 2, 4, 8, 16, 32, and 64.

I am going to try understanding how that works in Rakudo. First of all, look into the src/core/operators.pm file, which keeps a lot of different operators, including a few versions of the ... operator. The one we need looks really simple:

multi sub infix:<...>(\a, Mu \b) {
Seq.new(SEQUENCE(a, b).iterator)
}

Now, the main work is done inside the SEQUENCE sub. Before we dive there, it is important to understand what its arguments a and b receive.

In the case of, say, 3, 5 ... 11, the first argument is a list 3, 5, and the second argument is a single value 11.

These values land in the parameters of the routine:

sub SEQUENCE(\left, Mu \right, :$exclude_end) {
. . .
}

What happens next is not that easy to grasp. Here is a screenshot of the complete function:

It contains about 350 lines of code and includes a couple of functions. Nevertheless, let’s try.

What you see first, is creating iterators for both left and right operands:

my \righti := (nqp::iscont(right) ?? right !! [right]).iterator;

my \lefti := left.iterator;

Then, the code loops over the left operand and builds an array @tail out of its data:

Redeclaration of a variable

Examine the following program:

my $x = 1;
my $x = 2;
say $x;

You can immediately see that this program is not entirely correct. Either we meant to assign a new value to $x or to create a new variable with a different name. In either case, compiler has no idea and complains: