🎄 3/25. Generating random integers in Perl 6

Welcome to Day 3 of the Perl 6 One-Liner Advent Calendar! Today, we will generate random numbers.

You may ask, what’s the deal with it, isn’t it a routine task to call a kind of a rand function? Well, in some sense, yes, but in Perl 6, you might prefer calling a method

Let’s look at the code for August in the Perl 6 calendar:

2019.rand.Int.say

That’s the whole program, and it generates random numbers below 2019! It only uses method calls, chained one after another. If you have never seen Perl 6 before, the first thing you notice here is a method called on a number. In Perl 6 that’s not something extraordinary.

Calling the rand method on a number potentially is a call of the method defined in the Cool class, which is immediately delegated to a numeric representation of the number:

method rand() { self.Num.rand }

Later in the Num class, a call to the underlying NQP engine happens:

method rand(Num:D: ) {
nqp::p6box_n(nqp::rand_n(nqp::unbox_n(self)));
}

In our example, the object 2019 is an Int, so rand is dispatched directly to the method of the Num class.

The rand method returns a floating-point number, so call Int on it to get an integer.

Run the code a few times to confirm that it generates random numbers:

$ perl6 -e'2019.rand.Int.say'
543
$ perl6 -e'2019.rand.Int.say'
1366
$ perl6 -e'2019.rand.Int.say'
1870

If you want to understand the quality of the random number generator, dig deeper to NQP and MoarVM, and later to the backend engine of the virtual machine. To make the results repeatable (e. g., for tests), set the seed by calling the srand function:

$ perl6 -e'srand(10); 2019.rand.Int.say'
296
$ perl6 -e'srand(10); 2019.rand.Int.say'
296

Notice that the srand routine is a subroutine, not a method. It is also defined in the same Num class:

proto sub srand($, *%) {*}
multi sub srand(Int:D $seed --> Int:D) {
nqp::p6box_i(nqp::srand($seed))
}

And if you have the chance to see the source file, you would most likely notice that there’s also a standalone subroutine for rand:

proto sub rand(*%) {*}
multi sub rand(--> Num:D) {
nqp::p6box_n(nqp::rand_n(1e0))
}

You can only call it without arguments, in which case Perl 6 generates a random number between 0 and 1. Would you pass the argument, you’ll get an error explaining that a method call is preferable:

$ perl6 -e'rand(20)'
===SORRY!=== Error while compiling -e
Unsupported use of rand(N); in Perl 6 please use N.rand for Num or (^N).pick for Int result
at -e:1
------> rand⏏(20)

OK, we dived quite deep from the initial one-liner, so let’s meet tomorrow with another piece of awesome Perl 6 code!

🎄 2/25. Grepping dividable numbers in Perl 6

Welcome to Day 2 of the Perl 6 One-Liner Advent Calendar! Today, we’ll solve a nice task from Project Euler with number 1. Once again, let me warn you that the rest of the text contains a solution, so you are welcome to make a pause to think of your own solution first. But I am almost sure that if you are reading perl6.online then you most likely solved the problems from Project Euler in the past.

The task is to find the sum of all multiples of 3 and 5 below 1000. The first elements of the row of our interest are 3, 5, 9, 15, 20, 21, etc. You can already see that some of them, such as 15, are multiples of both 3 and 5, so it is not possible to add up multiples of 3 and 5 separately.

The short story is here:

say sum((1..999).grep: * %% (3 | 5))

Now let us decipher it.

What we need is to filter the numbers that are multiples of either 3 or 5. If you re-read the previous sentence, a bell should ring for you: in Perl 6 this can be achieved with junctions, informally known as quantum superpositions. To test if a number is dividable by either 3 or 5, write the following:

$x %% 3 | 5

By the way, %%, the divisibility operator, is a very sweet thing that helps avoiding negations in Boolean tests, which you would have written as follows, would you only have a single percent:

!($x % (3 | 5))

OK, the main condition is ready, let us scan the numbers between 1 and (including) 999:

(1..999).grep: * %% (3 | 5)

A few more interesting Perl 6 elements appear here. For example, the WhateverCode block, which was introduced by a * character (learn more about it in my article All the stars of Perl 6 published in the previous Perl 6 Advent Calendar). Together with the colon-form of method calls, it allows to get rid of a nested pair of braces and parentheses:

(1..999).grep({$_ %% (3 | 5)})

The numbers are filtered (grepped if you prefer), and it’s time to add them up and print the result. We come to the final one-liner shown at the beginning of this post.

Of course, instead of writing say sum(...) one could do a method call or two:

((1..999).grep: * %% (3 | 5)).sum.say

As a bonus track, here’s my first solution:

sub f($n) {
    ($n <<*>> (1...1000 / $n)).grep: * < 1000
}

say (f(3) ∪ f(5)).keys.sum;

And that’s the end of today’s story! Come again tomorrow!

🎄 1/25. Generating random passwords in Perl 6

Welcome to the first day of the brand new Perl6.Online Advent Calendar! This year, its theme is Perl 6 One-Liners (a pun from perl6.onliners). Thus, welcome to this year’s Perl 6 One-Liner Advent Calendar. The whole perl6.online blog was initially planned to be daily, so it’s a great opportunity to keep the pace for at least another 25 days.

Don’t forget to follow other Perl-related calendars written by other people:

In the following days, I will be publishing short articles that either explain the code from the Perl 6 Calendar 2019 or solve some problems inspired by Project Euler, where Perl 6 can demonstrate its extreme beauty (if you don’t want to see my solutions prior to yours, I invite you to solve the tasks yourself first, and only then read the articles). But today, let’s start with something else and generate a random password in Perl 6.

Here’s the full code:

('0'..'z').pick(15).join.say

Run it a few times:

Z4x72B8wkWHo0QD
J;V?=CE84jIS^r9
2;m6>kdHRS04XEL
O6wK=umZ]DqyHT5
3SP\tNkX5Zh@1C4
PX6QC?KdWYyzNOc
bq1EfBZNdK9vHxz

Our line generates different strings each time you run it. Try it yourself to create a password or take one of the above-shown passwords if you did not install Perl 6 yet.

Some time ago, we looked into the internals of the pick method. It is defined in the Any class, and it actually is delegating work to the method of the List class:

proto method pick(|) is nodal {*}
multi method pick() { self.list.pick }
multi method pick($n) { self.list.pick($n) }

The join method is defined in the List class too. Let’s not examine the body of it now, as it is quite big, but let’s look at the signature:

method join(List:D: Str(Cool) $separator = '') is nodal

It is clearly seen that when invoking the method with no arguments, the default separator is an empty string, which is exactly what we need for passwords. (Learn more about the is nodal trait in the documentation; it is said there that the trait is not supposed to be widely used in common code.)

You may also ask a question: What characters can I expect in the password? Great that you ask! Perl 6 is a Unicode-oriented language, and the range '0'..'z' seems to contain characters with different Unicode properties (i. e., digits and letters at least). To see what’s inside, just remove the pick method from our today’s code:

('0'..'z').join.say

This line prints the subset of the ASCII table between the two given characters:

0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
abcdefghijklmnopqrstuvwxyz

These are the characters that may appear in the password. The pick method makes sure characters are not repeated.

And that’s all for today, see you tomorrow with another line of Perl 6 code.

📘 Variables in Perl 6: Introspection

Due to the mechanism of introspection, it is easily possible to tell the type of the data living in a variable (a variable in Perl 6 is often referred as a container). To do that, call the predefined WHAT method on a variable. Even if it is a bare scalar, Perl 6 treats it internally as an object; thus, you may call some methods on it.

For scalars, the result depends on the real type of data residing in a variable. Here is an example (parentheses are part of the output):

my $scalar = 42;
my $hello-world = "Hello, World";

say $scalar.WHAT;      # (Int)
say $hello-world.WHAT; # (Str)

For those variables, whose names start with the sigils @ and %, the WHAT method returns the strings (Array) and (Hash).

Try with arrays:

my @list = 10, 20, 30;
my @squares = 0, 1, 4, 9, 16, 25;

say @list.WHAT;    # (Array)
say @squares.WHAT; # (Array)

Now with hashes:

my %hash = 'Language' => 'Perl';
my %capitals = 'France' => 'Paris';

say %hash.WHAT;     # (Hash)
say %capitals.WHAT; # (Hash)

The thing, which is returned after a WHAT call, is a so-called type object. In Perl 6, you should use the === operator to compare these objects.

For instance:

my $value = 42;
say "OK" if $value.WHAT === Int;

There’s an alternative way to check the type of an object residing in a container — the isa method. Call it on an object, passing the type name as an argument, and get the answer:

my $value = 42;
say "OK" if $value.isa(Int);