🎄 5/25. What’s the date today in Perl 6?

Welcome to Day 5 of this lovely Perl 6 One-Liner Advent Calendar!

Today, we’ll answer the question of what’s the date today (and tomorrow we can talk about palindromes if you want).

So, to print the answer, you can use the following line of Perl 6 code:

DateTime.now.yyyy-mm-dd.say

It looks transparent and prints the date in the format of YYYY-MM-DD. The good part is that the DateTime class is available straight ahead, and you don’t need to include a module as you do in Perl 5, for example.

$ perl6 -e'DateTime.now.yyyy-mm-dd.say'
2018-12-05

As you have already seen in the previous days of the calendar, chaining method calls is a typical Perl 6 thing. An opposite alternative would be to use say as a subroutine and use parentheses to mark method calls:

say(DateTime.now().yyyy-mm-dd());

This code also works; it is completely correct, but it looks heavy.

What you should also notice and tell your friends, is that in Perl 6, you can use dashes and apostrophes in identifiers.

Well, maybe using apostrophes is not a great idea, but hyphens are used very widely already in the source code of Perl 6. Just make sure you put spaces around minus operator in expressions to avoid any conflicts in parsing.

Exploring the sources or reading the documentation, you will find another method named in the same manner: hh-mm-ss. I bet you understand what it does.

> DateTime.now.hh-mm-ss.say
00:12:01

Notice that you will not find similar methods for different formats of the output, such as dd-mm-yy or hh-mm. Use formatter instead. It is not a method but an attribute defined in the Datish role. There is a default formatter in the DateTime class, but you may redefine it by providing the constructor with your own subroutine, for example:

DateTime.now(formatter => -> $dt {
sprintf '%02d.%02d.%04d',
$dt.day, $dt.month, $dt.year
}).say

A formatter here takes an anonymous subroutine (introduces by an arrow) with one argument $dt.

I hope this code prints the same date as our initial one-liner, as you most likely read the whole article within one day.

Nevertheless, see you tomorrow with a code that tests palindromes! 

🎄 4/25. Working with big numbers in Perl 6

Welcome to Day 4 of the Perl 6 One-Liner Advent Calendar!

Today, we’ll look at the Problem 13 of Project Euler. Let me show a screenshot of it:

Indeed, it looks huge, and the task is to find the first ten digits of the sum of a hundred integers, each consisting of 50 digits.

Sounds like a task that may require some optimisation and simplification to get rid of everything which does not contribute to the first ten digits of the result. But not in Perl 6.

In Perl 6, you can simply add up the numbers and take the first ten digits of it:

<
37107287433902102798797998220837590246510135740250
# Other 98 numbers here
53503534526472524250874054075591789781264330331690
>.sum.substr(0, 10).say

Perl 6 is operating with arbitrary-long integers by default; you don’t need to include any modules or somehow else activate this behaviour. You can even calculate powers and get the result quickly enough:

$ perl6 -e'say 37107287433902102798797998220837590 ** 1000'

Another thing to notice is that we can transparently cast strings to numbers and vice versa. In our today’s program, the list of numbers is presented as a quoted list of strings within a pair of angle brackets.

On the list, you call the sum method, which works with numbers. After getting the sum, you treat it as a string again and extract the first ten characters of it. The whole code looks very natural and easy to read.

And with this mood, we’ll say ‘Goodbye’ till tomorrow!

🎄 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.