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!
I love all the work being done on Perl6! I have decided to learn it even though I don’t know what I will use it for. At least, not yet.